diff --git a/ruoyi-system/src/main/java/com/ruoyi/jarvis/util/TencentDocApiUtil.java b/ruoyi-system/src/main/java/com/ruoyi/jarvis/util/TencentDocApiUtil.java index b8d2c5a..12ac11d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/jarvis/util/TencentDocApiUtil.java +++ b/ruoyi-system/src/main/java/com/ruoyi/jarvis/util/TencentDocApiUtil.java @@ -23,6 +23,12 @@ import java.nio.charset.StandardCharsets; public class TencentDocApiUtil { private static final Logger log = LoggerFactory.getLogger(TencentDocApiUtil.class); + + /** + * 在线表格 batchUpdate 单次请求中操作数上限(官方:单次操作数量小于等于 5) + * @see 批量更新接口 + */ + public static final int TENCENT_BATCH_UPDATE_MAX_OPERATIONS = 5; // 静态初始化块:禁用系统代理,确保腾讯文档API调用直接连接 static { @@ -456,12 +462,50 @@ public class TencentDocApiUtil { */ public static JSONObject batchUpdate(String accessToken, String appId, String openId, String fileId, JSONObject requestBody, String apiBaseUrl) { String apiUrl = String.format("%s/files/%s/batchUpdate", apiBaseUrl, fileId); - - log.info("批量更新表格(batchUpdate)- fileId: {}, requests数量: {}", - fileId, requestBody.getJSONArray("requests") != null ? requestBody.getJSONArray("requests").size() : 0); - log.debug("批量更新表格 - 请求体: {}", requestBody.toJSONString()); - - return callApi(accessToken, appId, openId, apiUrl, "POST", requestBody.toJSONString()); + + JSONArray requests = requestBody != null ? requestBody.getJSONArray("requests") : null; + if (requests == null || requests.isEmpty()) { + throw new IllegalArgumentException("batchUpdate 请求体缺少非空 requests 数组"); + } + + int total = requests.size(); + log.info("批量更新表格(batchUpdate)- fileId: {}, 总操作数: {}(每批最多 {} 条)", + fileId, total, TENCENT_BATCH_UPDATE_MAX_OPERATIONS); + + JSONObject lastResult = null; + for (int start = 0; start < total; start += TENCENT_BATCH_UPDATE_MAX_OPERATIONS) { + int end = Math.min(start + TENCENT_BATCH_UPDATE_MAX_OPERATIONS, total); + JSONArray chunk = new JSONArray(); + for (int i = start; i < end; i++) { + chunk.add(requests.get(i)); + } + JSONObject chunkBody = new JSONObject(); + chunkBody.put("requests", chunk); + + log.info("batchUpdate 分片 {}-{} / {}, 本批 {} 条", start + 1, end, total, chunk.size()); + log.debug("批量更新表格 - 分片请求体: {}", chunkBody.toJSONString()); + + lastResult = callApi(accessToken, appId, openId, apiUrl, "POST", chunkBody.toJSONString()); + assertSpreadsheetBatchUpdateSuccess(lastResult); + } + return lastResult != null ? lastResult : new JSONObject(); + } + + /** + * V3 表格接口在 HTTP 200 时仍可能在 body 内返回 code!=0(如单次 batch 超过 5 条) + */ + private static void assertSpreadsheetBatchUpdateSuccess(JSONObject result) { + if (result == null) { + return; + } + if (result.containsKey("code")) { + int code = result.getIntValue("code"); + if (code != 0) { + String msg = result.getString("message"); + log.error("腾讯文档 batchUpdate 业务失败: code={}, message={}", code, msg); + throw new RuntimeException("腾讯文档 batchUpdate 失败: " + msg + " (code=" + code + ")"); + } + } } /**