1
This commit is contained in:
@@ -57,8 +57,10 @@ public class TencentDocController extends BaseController {
|
|||||||
/** Redis key前缀,用于存储上次处理的最大行数 */
|
/** Redis key前缀,用于存储上次处理的最大行数 */
|
||||||
private static final String LAST_PROCESSED_ROW_KEY_PREFIX = "tendoc:last_row:";
|
private static final String LAST_PROCESSED_ROW_KEY_PREFIX = "tendoc:last_row:";
|
||||||
|
|
||||||
/** 单次请求最大行数(腾讯文档 API range 限制,避免 invalid param range) */
|
/** 单次请求最大行数(腾讯文档 API:行数≤1000,一次拉 500 行) */
|
||||||
private static final int API_MAX_ROWS_PER_REQUEST = 200;
|
private static final int API_MAX_ROWS_PER_REQUEST = 500;
|
||||||
|
/** 数据区 range 列尾(30 列 = A 到 AD,API 列数≤200) */
|
||||||
|
private static final String DATA_RANGE_COL_END = "AD";
|
||||||
/** 回溯行数:下次起始行 = 本次扫描终点 + 1 - 回溯,用于覆盖物流变更或延后补填 */
|
/** 回溯行数:下次起始行 = 本次扫描终点 + 1 - 回溯,用于覆盖物流变更或延后补填 */
|
||||||
private static final int BACKTRACK_ROWS = 80;
|
private static final int BACKTRACK_ROWS = 80;
|
||||||
/** 整批都跳过(0 写入)时使用的回溯行数,减小回溯以尽快扫到后续行(如 308) */
|
/** 整批都跳过(0 写入)时使用的回溯行数,减小回溯以尽快扫到后续行(如 308) */
|
||||||
@@ -1168,7 +1170,7 @@ public class TencentDocController extends BaseController {
|
|||||||
if (tryEndRow < startRow) {
|
if (tryEndRow < startRow) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String range = String.format("A%d:Z%d", startRow, tryEndRow);
|
String range = String.format("A%d:%s%d", startRow, DATA_RANGE_COL_END, tryEndRow);
|
||||||
log.info("开始读取数据行 - 行号: {} ~ {} (共 {} 行), range: {} (尝试 decrement={})", startRow, tryEndRow, tryRowCount, range, decrement);
|
log.info("开始读取数据行 - 行号: {} ~ {} (共 {} 行), range: {} (尝试 decrement={})", startRow, tryEndRow, tryRowCount, range, decrement);
|
||||||
try {
|
try {
|
||||||
sheetData = tencentDocService.readSheetData(accessToken, fileId, sheetId, range);
|
sheetData = tencentDocService.readSheetData(accessToken, fileId, sheetId, range);
|
||||||
@@ -1198,7 +1200,7 @@ public class TencentDocController extends BaseController {
|
|||||||
for (int decrement : new int[] { 1, 10 }) {
|
for (int decrement : new int[] { 1, 10 }) {
|
||||||
int tryEndRow = Math.max(startRow, effectiveEndRow - decrement);
|
int tryEndRow = Math.max(startRow, effectiveEndRow - decrement);
|
||||||
if (tryEndRow >= startRow) {
|
if (tryEndRow >= startRow) {
|
||||||
String retryRange = String.format("A%d:Z%d", startRow, tryEndRow);
|
String retryRange = String.format("A%d:%s%d", startRow, DATA_RANGE_COL_END, tryEndRow);
|
||||||
try {
|
try {
|
||||||
sheetData = tencentDocService.readSheetData(accessToken, fileId, sheetId, retryRange);
|
sheetData = tencentDocService.readSheetData(accessToken, fileId, sheetId, retryRange);
|
||||||
if (sheetData != null) {
|
if (sheetData != null) {
|
||||||
@@ -1221,7 +1223,7 @@ public class TencentDocController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
endRow = effectiveEndRow; // 后续统一使用实际读取成功的 endRow
|
endRow = effectiveEndRow; // 后续统一使用实际读取成功的 endRow
|
||||||
String range = String.format("A%d:Z%d", startRow, endRow);
|
String range = String.format("A%d:%s%d", startRow, DATA_RANGE_COL_END, endRow);
|
||||||
log.info("解析后的数据行数: {}", values != null ? values.size() : "null");
|
log.info("解析后的数据行数: {}", values != null ? values.size() : "null");
|
||||||
|
|
||||||
if (values == null || values.isEmpty()) {
|
if (values == null || values.isEmpty()) {
|
||||||
@@ -2122,8 +2124,8 @@ public class TencentDocController extends BaseController {
|
|||||||
int skippedCount = 0;
|
int skippedCount = 0;
|
||||||
int errorCount = 0;
|
int errorCount = 0;
|
||||||
|
|
||||||
// 分批读取数据,每批200行(避免单次读取过多数据导致API限制)
|
// 分批读取数据,每批500行(API 行数≤1000,列数≤200)
|
||||||
final int BATCH_SIZE = 200;
|
final int BATCH_SIZE = 500;
|
||||||
int currentStartRow = startRow;
|
int currentStartRow = startRow;
|
||||||
int totalBatches = (int) Math.ceil((double)(endRow - startRow + 1) / BATCH_SIZE);
|
int totalBatches = (int) Math.ceil((double)(endRow - startRow + 1) / BATCH_SIZE);
|
||||||
int currentBatch = 0;
|
int currentBatch = 0;
|
||||||
@@ -2421,8 +2423,8 @@ public class TencentDocController extends BaseController {
|
|||||||
int errorCount = 0; // 错误数量
|
int errorCount = 0; // 错误数量
|
||||||
java.util.List<String> updatedOrderNos = new java.util.ArrayList<>(); // 更新的单号列表
|
java.util.List<String> updatedOrderNos = new java.util.ArrayList<>(); // 更新的单号列表
|
||||||
|
|
||||||
// 分批读取数据,每批200行(避免单次读取过多数据导致API限制)
|
// 分批读取数据,每批500行(API 行数≤1000,列数≤200)
|
||||||
final int BATCH_SIZE = 200;
|
final int BATCH_SIZE = 500;
|
||||||
int currentStartRow = startRow;
|
int currentStartRow = startRow;
|
||||||
int totalBatches = (int) Math.ceil((double)(endRow - startRow + 1) / BATCH_SIZE);
|
int totalBatches = (int) Math.ceil((double)(endRow - startRow + 1) / BATCH_SIZE);
|
||||||
int currentBatch = 0;
|
int currentBatch = 0;
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS
|
|||||||
"AUTO",
|
"AUTO",
|
||||||
"DELAYED_TIMER",
|
"DELAYED_TIMER",
|
||||||
startRow,
|
startRow,
|
||||||
startRow + 199 // 与 Controller API_MAX_ROWS_PER_REQUEST=200 一致(单批最多200行)
|
startRow + 499 // 与 Controller API_MAX_ROWS_PER_REQUEST=500 一致(单批最多500行)
|
||||||
);
|
);
|
||||||
log.info("✓ 创建批量推送记录,批次ID: {}", batchId);
|
log.info("✓ 创建批量推送记录,批次ID: {}", batchId);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
@@ -344,9 +345,15 @@ public class TencentDocApiUtil {
|
|||||||
*/
|
*/
|
||||||
public static JSONObject readSheetData(String accessToken, String appId, String openId, String fileId, String sheetId, String range, String apiBaseUrl) {
|
public static JSONObject readSheetData(String accessToken, String appId, String openId, String fileId, String sheetId, String range, String apiBaseUrl) {
|
||||||
// V3版本API路径格式:/openapi/spreadsheet/v3/files/{fileId}/{sheetId}/{range}
|
// V3版本API路径格式:/openapi/spreadsheet/v3/files/{fileId}/{sheetId}/{range}
|
||||||
// range格式:A1表示法(Excel格式),如 A10:D11
|
// range 需 URL 编码,否则 path 中的 ":" 会导致网关/服务端报 range invalid (400001)
|
||||||
String apiUrl = String.format("%s/files/%s/%s/%s", apiBaseUrl, fileId, sheetId, range);
|
String encodedRange;
|
||||||
log.info("读取表格数据 - fileId: {}, sheetId: {}, range: {}, apiUrl: {}", fileId, sheetId, range, apiUrl);
|
try {
|
||||||
|
encodedRange = URLEncoder.encode(range, StandardCharsets.UTF_8.name());
|
||||||
|
} catch (java.io.UnsupportedEncodingException e) {
|
||||||
|
encodedRange = range.replace(":", "%3A");
|
||||||
|
}
|
||||||
|
String apiUrl = String.format("%s/files/%s/%s/%s", apiBaseUrl, fileId, sheetId, encodedRange);
|
||||||
|
log.info("读取表格数据 - fileId: {}, sheetId: {}, range: {} (encoded: {}), apiUrl: {}", fileId, sheetId, range, encodedRange, apiUrl);
|
||||||
return callApi(accessToken, appId, openId, apiUrl, "GET", null);
|
return callApi(accessToken, appId, openId, apiUrl, "GET", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user