This commit is contained in:
Leo
2025-11-16 00:12:07 +08:00
parent 276fb49354
commit 01f0be6198

View File

@@ -1789,117 +1789,168 @@ public class TencentDocController extends BaseController {
return AjaxResult.error("无法识别表头列,请确保表头包含'单号'和'物流单号'列");
}
// 读取数据行
String dataRange = String.format("A%d:Z%d", startRow, endRow);
log.info("读取数据范围: {}", dataRange);
JSONObject dataResponse = tencentDocService.readSheetData(accessToken, fileId, sheetId, dataRange);
if (dataResponse == null || !dataResponse.containsKey("values")) {
return AjaxResult.error("读取数据失败");
}
JSONArray rows = dataResponse.getJSONArray("values");
if (rows == null || rows.isEmpty()) {
return AjaxResult.error("数据为空");
}
// 统计结果
int successCount = 0;
int skippedCount = 0;
int errorCount = 0;
// 处理每一行
for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) {
JSONArray row = rows.getJSONArray(rowIndex);
if (row == null || row.size() <= Math.max(orderNoColumn, logisticsLinkColumn)) {
skippedCount++;
continue;
}
// 分批读取数据每批200行避免单次读取过多数据导致API限制
final int BATCH_SIZE = 200;
int currentStartRow = startRow;
int totalBatches = (int) Math.ceil((double)(endRow - startRow + 1) / BATCH_SIZE);
int currentBatch = 0;
log.info("开始分批处理,共 {} 批,每批 {} 行", totalBatches, BATCH_SIZE);
while (currentStartRow <= endRow) {
currentBatch++;
int currentEndRow = Math.min(currentStartRow + BATCH_SIZE - 1, endRow);
int actualRow = startRow + rowIndex;
String logisticsLink = row.getString(logisticsLinkColumn);
String orderNoFromDoc = row.getString(orderNoColumn);
log.info("正在处理第 {}/{} 批:第 {} 行到第 {} 行", currentBatch, totalBatches, currentStartRow, currentEndRow);
// 跳过物流链接为空的
if (logisticsLink == null || logisticsLink.trim().isEmpty()) {
log.debug("跳过第 {} 行:物流链接为空", actualRow);
skippedCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, null,
"SKIPPED", "物流链接为空");
continue;
}
// 跳过单号为空的行
if (orderNoFromDoc == null || orderNoFromDoc.trim().isEmpty()) {
log.debug("跳过第 {} 行:单号为空", actualRow);
skippedCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, logisticsLink,
"SKIPPED", "单号为空");
continue;
}
// 清理物流链接(去除空格、换行符、中文等)
logisticsLink = cleanLogisticsLink(logisticsLink);
// 读取当前批次的数据
String dataRange = String.format("A%d:Z%d", currentStartRow, currentEndRow);
log.info("读取数据范围: {}", dataRange);
JSONObject dataResponse = null;
try {
// 通过物流链接查找订单
JDOrder order = jdOrderService.selectJDOrderByLogisticsLink(logisticsLink);
if (order == null) {
log.warn("未找到匹配的订单 - 行: {}, 物流链接: {}", actualRow, logisticsLink);
errorCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, logisticsLink,
"FAILED", "未找到匹配的订单");
dataResponse = tencentDocService.readSheetData(accessToken, fileId, sheetId, dataRange);
} catch (Exception e) {
log.error("读取第 {} 批数据失败({} - {} 行)", currentBatch, currentStartRow, currentEndRow, e);
errorCount += (currentEndRow - currentStartRow + 1);
// 继续处理下一批
currentStartRow = currentEndRow + 1;
continue;
}
if (dataResponse == null || !dataResponse.containsKey("values")) {
log.warn("第 {} 批数据读取返回空({} - {} 行),跳过", currentBatch, currentStartRow, currentEndRow);
currentStartRow = currentEndRow + 1;
continue;
}
JSONArray rows = dataResponse.getJSONArray("values");
if (rows == null || rows.isEmpty()) {
log.info("第 {} 批数据为空({} - {} 行),跳过", currentBatch, currentStartRow, currentEndRow);
currentStartRow = currentEndRow + 1;
continue;
}
log.info("第 {} 批读取到 {} 行数据", currentBatch, rows.size());
// 处理当前批次的每一行
for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) {
JSONArray row = rows.getJSONArray(rowIndex);
if (row == null || row.size() <= Math.max(orderNoColumn, logisticsLinkColumn)) {
skippedCount++;
continue;
}
// 检查订单是否已有第三方单号(如果已有且与文档中的不同,跳过)
if (order.getThirdPartyOrderNo() != null && !order.getThirdPartyOrderNo().trim().isEmpty()) {
if (!order.getThirdPartyOrderNo().trim().equals(orderNoFromDoc.trim())) {
log.info("跳过第 {} 行:订单已有第三方单号且不同 - 现有: {}, 文档: {}",
actualRow, order.getThirdPartyOrderNo(), orderNoFromDoc);
skippedCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", order.getRemark(), actualRow, logisticsLink,
"SKIPPED", "订单已有第三方单号且不同");
int actualRow = currentStartRow + rowIndex;
// 确保不超过结束行
if (actualRow > endRow) {
break;
}
String logisticsLink = row.getString(logisticsLinkColumn);
String orderNoFromDoc = row.getString(orderNoColumn);
// 跳过物流链接为空的行
if (logisticsLink == null || logisticsLink.trim().isEmpty()) {
log.debug("跳过第 {} 行:物流链接为空", actualRow);
skippedCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, null,
"SKIPPED", "物流链接为空");
continue;
}
// 跳过单号为空的行
if (orderNoFromDoc == null || orderNoFromDoc.trim().isEmpty()) {
log.debug("跳过第 {} 行:单号为空", actualRow);
skippedCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, logisticsLink,
"SKIPPED", "单号为空");
continue;
}
// 清理物流链接(去除空格、换行符、中文等)
logisticsLink = cleanLogisticsLink(logisticsLink);
try {
// 通过物流链接查找订单
JDOrder order = jdOrderService.selectJDOrderByLogisticsLink(logisticsLink);
if (order == null) {
log.warn("未找到匹配的订单 - 行: {}, 物流链接: {}", actualRow, logisticsLink);
errorCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, logisticsLink,
"FAILED", "未找到匹配的订单");
continue;
}
// 如果相同,继续执行(清除物流链接)
}
// 更新订单的第三方单号
order.setThirdPartyOrderNo(orderNoFromDoc.trim());
int updateResult = jdOrderService.updateJDOrder(order);
if (updateResult <= 0) {
log.error("更新订单失败 - 行: {}, 订单ID: {}, 单号: {}",
actualRow, order.getId(), order.getRemark());
errorCount++;
// 检查订单是否已有第三方单号(如果已有且与文档中的不同,跳过)
if (order.getThirdPartyOrderNo() != null && !order.getThirdPartyOrderNo().trim().isEmpty()) {
if (!order.getThirdPartyOrderNo().trim().equals(orderNoFromDoc.trim())) {
log.info("跳过第 {} 行:订单已有第三方单号且不同 - 现有: {}, 文档: {}",
actualRow, order.getThirdPartyOrderNo(), orderNoFromDoc);
skippedCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", order.getRemark(), actualRow, logisticsLink,
"SKIPPED", "订单已有第三方单号且不同");
continue;
}
// 如果相同,继续执行(清除物流链接)
}
// 更新订单的第三方单号
order.setThirdPartyOrderNo(orderNoFromDoc.trim());
int updateResult = jdOrderService.updateJDOrder(order);
if (updateResult <= 0) {
log.error("更新订单失败 - 行: {}, 订单ID: {}, 单号: {}",
actualRow, order.getId(), order.getRemark());
errorCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", order.getRemark(), actualRow, logisticsLink,
"FAILED", "更新订单失败");
continue;
}
log.info("✓ 更新订单成功 - 行: {}, 订单: {}, 第三方单号: {}",
actualRow, order.getRemark(), orderNoFromDoc);
successCount++;
// 记录成功日志
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", order.getRemark(), actualRow, logisticsLink,
"FAILED", "更新订单失败");
continue;
"SUCCESS", String.format("已将单号 %s 写入订单的第三方单号字段", orderNoFromDoc));
} catch (Exception e) {
log.error("处理第 {} 行失败", actualRow, e);
errorCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, logisticsLink,
"FAILED", "处理异常: " + e.getMessage());
}
log.info("✓ 更新订单成功 - 行: {}, 订单: {}, 第三方单号: {}",
actualRow, order.getRemark(), orderNoFromDoc);
successCount++;
// 记录成功日志
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", order.getRemark(), actualRow, logisticsLink,
"SUCCESS", String.format("已将单号 %s 写入订单的第三方单号字段", orderNoFromDoc));
} catch (Exception e) {
log.error("处理第 {} 行失败", actualRow, e);
errorCount++;
logOperation(batchId, fileId, sheetId, "REVERSE_SYNC", null, actualRow, logisticsLink,
"FAILED", "处理异常: " + e.getMessage());
// 添加延迟避免API调用频率过高
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 添加延迟避免API调用频率过高
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.info("第 {}/{} 批处理完成,当前统计 - 成功: {}, 跳过: {}, 错误: {}",
currentBatch, totalBatches, successCount, skippedCount, errorCount);
// 移动到下一批
currentStartRow = currentEndRow + 1;
// 批次之间的延迟避免API调用频率过高
if (currentStartRow <= endRow) {
try {
Thread.sleep(200); // 批次之间延迟200ms
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}