1
This commit is contained in:
450
doc/物流链接自动填充-多字段更新功能.md
Normal file
450
doc/物流链接自动填充-多字段更新功能.md
Normal file
@@ -0,0 +1,450 @@
|
||||
# 物流链接自动填充 - 多字段更新功能
|
||||
|
||||
## ✅ 新功能说明
|
||||
|
||||
在成功匹配订单并写入物流链接的同时,自动更新以下三个字段:
|
||||
|
||||
| 字段 | 写入内容 | 说明 |
|
||||
|------|----------|------|
|
||||
| **物流单号** | 物流链接 URL | 从数据库中查询到的物流链接 |
|
||||
| **是否安排** | `2` | 固定值,表示已安排 |
|
||||
| **标记** | 当天日期 | 格式:`yyMMdd`(如:`251105`) |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 实现效果
|
||||
|
||||
### 修改前(只更新一个字段)
|
||||
|
||||
```
|
||||
写入物流链接 - 单元格: M3, 单号: JY2025110329041
|
||||
```
|
||||
|
||||
**表格更新**:
|
||||
| 行 | 单号 | ... | 物流单号 | 是否安排 | 标记 |
|
||||
|----|------|-----|----------|----------|------|
|
||||
| 3 | JY2025110329041 | ... | ✅ https://... | (空) | (空) |
|
||||
|
||||
---
|
||||
|
||||
### 修改后(同时更新三个字段)
|
||||
|
||||
```
|
||||
成功写入数据 - 行: 3, 单号: JY2025110329041,
|
||||
物流链接: https://3.cn/2ume-Ak1, 是否安排: 2, 标记: 251105
|
||||
```
|
||||
|
||||
**表格更新**:
|
||||
| 行 | 单号 | ... | 物流单号 | 是否安排 | 标记 |
|
||||
|----|------|-----|----------|----------|------|
|
||||
| 3 | JY2025110329041 | ... | ✅ https://... | ✅ 2 | ✅ 251105 |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术实现
|
||||
|
||||
### 1. 自动识别列位置
|
||||
|
||||
在读取表头时,自动识别所有相关列:
|
||||
|
||||
```java
|
||||
// 查找所有相关列
|
||||
for (int i = 0; i < headerRowData.size(); i++) {
|
||||
String cellValue = headerRowData.getString(i);
|
||||
if (cellValue != null) {
|
||||
String cellValueTrim = cellValue.trim();
|
||||
|
||||
// 识别"单号"列
|
||||
if (orderNoColumn == null && cellValueTrim.contains("单号")) {
|
||||
orderNoColumn = i;
|
||||
}
|
||||
|
||||
// 识别"物流单号"列
|
||||
if (logisticsLinkColumn == null && (cellValueTrim.contains("物流单号") || cellValueTrim.contains("物流链接"))) {
|
||||
logisticsLinkColumn = i;
|
||||
}
|
||||
|
||||
// 识别"是否安排"列
|
||||
if (arrangedColumn == null && cellValueTrim.contains("是否安排")) {
|
||||
arrangedColumn = i;
|
||||
}
|
||||
|
||||
// 识别"标记"列
|
||||
if (markColumn == null && cellValueTrim.contains("标记")) {
|
||||
markColumn = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**识别结果示例**:
|
||||
```
|
||||
识别到 '单号' 列:第 3 列(索引2)
|
||||
识别到 '物流单号' 列:第 13 列(索引12)
|
||||
识别到 '是否安排' 列:第 12 列(索引11)
|
||||
识别到 '标记' 列:第 15 列(索引14)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 获取当前日期
|
||||
|
||||
使用 `SimpleDateFormat` 格式化当前日期:
|
||||
|
||||
```java
|
||||
// 获取今天的日期,格式:yyMMdd(如:251105)
|
||||
String today = new java.text.SimpleDateFormat("yyMMdd").format(new java.util.Date());
|
||||
```
|
||||
|
||||
**日期格式示例**:
|
||||
| 日期 | 格式化结果 |
|
||||
|------|-----------|
|
||||
| 2025年11月5日 | `251105` |
|
||||
| 2025年11月1日 | `251101` |
|
||||
| 2025年12月31日 | `251231` |
|
||||
|
||||
---
|
||||
|
||||
### 3. 使用 batchUpdate 一次性更新多个字段
|
||||
|
||||
使用腾讯文档的 `batchUpdate` API,在一个请求中更新同一行的多个单元格:
|
||||
|
||||
```java
|
||||
// 使用 batchUpdate 一次性更新多个字段
|
||||
JSONArray requests = new JSONArray();
|
||||
|
||||
// 1. 更新物流单号
|
||||
requests.add(buildUpdateCellRequest(sheetId, row - 1, logisticsLinkColumn, logisticsLink));
|
||||
|
||||
// 2. 更新"是否安排"列(如果存在)
|
||||
if (arrangedColumn != null) {
|
||||
requests.add(buildUpdateCellRequest(sheetId, row - 1, arrangedColumn, "2"));
|
||||
}
|
||||
|
||||
// 3. 更新"标记"列(如果存在)
|
||||
if (markColumn != null) {
|
||||
requests.add(buildUpdateCellRequest(sheetId, row - 1, markColumn, today));
|
||||
}
|
||||
|
||||
// 构建完整的 batchUpdate 请求体
|
||||
JSONObject batchUpdateBody = new JSONObject();
|
||||
batchUpdateBody.put("requests", requests);
|
||||
|
||||
// 调用 batchUpdate API
|
||||
tencentDocService.batchUpdate(accessToken, fileId, batchUpdateBody);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. buildUpdateCellRequest 辅助方法
|
||||
|
||||
构建单个单元格的更新请求:
|
||||
|
||||
```java
|
||||
private JSONObject buildUpdateCellRequest(String sheetId, int rowIndex, int columnIndex, String value) {
|
||||
// 构建 updateRangeRequest
|
||||
JSONObject updateRangeRequest = new JSONObject();
|
||||
updateRangeRequest.put("sheetId", sheetId);
|
||||
|
||||
// 构建 gridData
|
||||
JSONObject gridData = new JSONObject();
|
||||
gridData.put("startRow", rowIndex);
|
||||
gridData.put("startColumn", columnIndex);
|
||||
|
||||
// 构建 rows 数组
|
||||
JSONArray rows = new JSONArray();
|
||||
JSONObject rowData = new JSONObject();
|
||||
JSONArray cellValues = new JSONArray();
|
||||
|
||||
// 构建单元格数据
|
||||
JSONObject cellData = new JSONObject();
|
||||
JSONObject cellValue = new JSONObject();
|
||||
cellValue.put("text", value);
|
||||
cellData.put("cellValue", cellValue);
|
||||
cellValues.add(cellData);
|
||||
|
||||
rowData.put("values", cellValues);
|
||||
rows.add(rowData);
|
||||
gridData.put("rows", rows);
|
||||
|
||||
updateRangeRequest.put("gridData", gridData);
|
||||
|
||||
// 包装为 request 对象
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("updateRangeRequest", updateRangeRequest);
|
||||
|
||||
return request;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 完整的 batchUpdate 请求示例
|
||||
|
||||
### 请求体结构
|
||||
|
||||
```json
|
||||
{
|
||||
"requests": [
|
||||
{
|
||||
"updateRangeRequest": {
|
||||
"sheetId": "BB08J2",
|
||||
"gridData": {
|
||||
"startRow": 2,
|
||||
"startColumn": 12,
|
||||
"rows": [
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"cellValue": {
|
||||
"text": "https://3.cn/2ume-Ak1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"updateRangeRequest": {
|
||||
"sheetId": "BB08J2",
|
||||
"gridData": {
|
||||
"startRow": 2,
|
||||
"startColumn": 11,
|
||||
"rows": [
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"cellValue": {
|
||||
"text": "2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"updateRangeRequest": {
|
||||
"sheetId": "BB08J2",
|
||||
"gridData": {
|
||||
"startRow": 2,
|
||||
"startColumn": 14,
|
||||
"rows": [
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"cellValue": {
|
||||
"text": "251105"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- 第1个请求:更新第3行(索引2)、第13列(索引12)- 物流单号
|
||||
- 第2个请求:更新第3行(索引2)、第12列(索引11)- 是否安排
|
||||
- 第3个请求:更新第3行(索引2)、第15列(索引14)- 标记
|
||||
|
||||
---
|
||||
|
||||
## 🔄 处理流程
|
||||
|
||||
```
|
||||
1. 读取表头
|
||||
├─ 识别"单号"列(必需)
|
||||
├─ 识别"物流单号"列(必需)
|
||||
├─ 识别"是否安排"列(可选)
|
||||
└─ 识别"标记"列(可选)
|
||||
|
||||
2. 读取数据行
|
||||
|
||||
3. 逐行处理
|
||||
├─ 提取单号
|
||||
├─ 查询数据库
|
||||
└─ 如果找到订单和物流链接
|
||||
├─ 构建 updateRangeRequest(物流单号)
|
||||
├─ 构建 updateRangeRequest(是否安排 = "2")- 如果列存在
|
||||
├─ 构建 updateRangeRequest(标记 = 当天日期)- 如果列存在
|
||||
└─ 调用 batchUpdate API 一次性更新
|
||||
|
||||
4. 返回统计结果
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 新增方法清单
|
||||
|
||||
### Controller 层(TencentDocController.java)
|
||||
|
||||
| 方法名 | 说明 |
|
||||
|--------|------|
|
||||
| `buildUpdateCellRequest` | 构建单个单元格的更新请求 |
|
||||
|
||||
**修改内容**:
|
||||
- ✅ 识别"是否安排"列和"标记"列
|
||||
- ✅ 获取当前日期(`yyMMdd` 格式)
|
||||
- ✅ 使用 `batchUpdate` 一次性更新多个字段
|
||||
|
||||
---
|
||||
|
||||
### Service 层(ITencentDocService.java / TencentDocServiceImpl.java)
|
||||
|
||||
| 方法名 | 说明 |
|
||||
|--------|------|
|
||||
| `batchUpdate` | 批量更新表格的接口方法 |
|
||||
|
||||
**接口定义**:
|
||||
```java
|
||||
/**
|
||||
* 批量更新表格(batchUpdate API)
|
||||
*
|
||||
* @param accessToken 访问令牌
|
||||
* @param fileId 文件ID
|
||||
* @param requestBody batchUpdate 请求体,包含 requests 数组
|
||||
* @return 更新结果
|
||||
*/
|
||||
JSONObject batchUpdate(String accessToken, String fileId, JSONObject requestBody);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Util 层(TencentDocApiUtil.java)
|
||||
|
||||
| 方法名 | 说明 |
|
||||
|--------|------|
|
||||
| `batchUpdate` | 调用腾讯文档 batchUpdate API 的静态方法 |
|
||||
|
||||
**方法签名**:
|
||||
```java
|
||||
public static JSONObject batchUpdate(
|
||||
String accessToken,
|
||||
String appId,
|
||||
String openId,
|
||||
String fileId,
|
||||
JSONObject requestBody,
|
||||
String apiBaseUrl
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
### 测试请求
|
||||
|
||||
```bash
|
||||
curl -X POST 'http://localhost:30313/jarvis/tencentDoc/fillLogisticsByOrderNo' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"accessToken": "YOUR_ACCESS_TOKEN",
|
||||
"fileId": "DUW50RUprWXh2TGJK",
|
||||
"sheetId": "BB08J2",
|
||||
"headerRow": 2
|
||||
}'
|
||||
```
|
||||
|
||||
### 预期日志
|
||||
|
||||
```
|
||||
识别到 '单号' 列:第 3 列(索引2)
|
||||
识别到 '物流单号' 列:第 13 列(索引12)
|
||||
识别到 '是否安排' 列:第 12 列(索引11)
|
||||
识别到 '标记' 列:第 15 列(索引14)
|
||||
|
||||
找到订单物流链接 - 单号: JY2025110329041, 物流链接: https://3.cn/2ume-Ak1, 行号: 3
|
||||
|
||||
批量更新表格(batchUpdate)- fileId: DUW50RUprWXh2TGJK, requests数量: 3
|
||||
|
||||
成功写入数据 - 行: 3, 单号: JY2025110329041,
|
||||
物流链接: https://3.cn/2ume-Ak1, 是否安排: 2, 标记: 251105
|
||||
```
|
||||
|
||||
### 预期结果
|
||||
|
||||
**返回 JSON**:
|
||||
```json
|
||||
{
|
||||
"msg": "填充物流链接完成",
|
||||
"code": 200,
|
||||
"data": {
|
||||
"filledCount": 45,
|
||||
"skippedCount": 3,
|
||||
"errorCount": 0,
|
||||
"message": "处理完成:成功填充 45 条,跳过 3 条,错误 0 条"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**表格变化**:
|
||||
| 单号 | 物流单号 | 是否安排 | 标记 |
|
||||
|------|----------|----------|------|
|
||||
| JY2025110329041 | ✅ https://3.cn/2ume-Ak1 | ✅ 2 | ✅ 251105 |
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 列必须存在
|
||||
|
||||
- **必需列**:单号、物流单号
|
||||
- **可选列**:是否安排、标记
|
||||
|
||||
如果表头中没有"是否安排"或"标记"列,系统会跳过这些字段的更新,不会报错。
|
||||
|
||||
### 2. 日期格式
|
||||
|
||||
日期格式固定为 `yyMMdd`:
|
||||
- 年份:2位数(如 `25` = 2025年)
|
||||
- 月份:2位数(如 `11` = 11月)
|
||||
- 日期:2位数(如 `05` = 5日)
|
||||
|
||||
### 3. API 调用次数
|
||||
|
||||
使用 `batchUpdate` 可以在一个请求中更新多个单元格,减少 API 调用次数:
|
||||
|
||||
**修改前**:每行调用1次 API(只更新物流单号)
|
||||
**修改后**:每行仍然调用1次 API(但一次更新3个字段)
|
||||
|
||||
✅ **API 调用次数不变,但更新的字段更多!**
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关官方文档
|
||||
|
||||
- [批量更新接口(batchUpdate)](https://docs.qq.com/open/document/app/openapi/v3/sheet/batchupdate/update.html)
|
||||
- [UpdateRangeRequest 说明](https://docs.qq.com/open/document/app/openapi/v3/sheet/batchupdate/request.html#updaterangerequest)
|
||||
|
||||
---
|
||||
|
||||
## ✅ 总结
|
||||
|
||||
### 功能增强
|
||||
|
||||
1. ✅ **自动识别更多列**:单号、物流单号、是否安排、标记
|
||||
2. ✅ **一次性更新多个字段**:物流单号 + 是否安排 + 标记
|
||||
3. ✅ **自动填充日期**:标记列自动填入当天日期(`yyMMdd` 格式)
|
||||
4. ✅ **状态标记**:"是否安排"列自动填入 `2`
|
||||
|
||||
### 技术优势
|
||||
|
||||
- ✅ 使用 `batchUpdate` API 一次性更新多个字段
|
||||
- ✅ API 调用次数不变,效率更高
|
||||
- ✅ 代码结构清晰,易于维护
|
||||
- ✅ 兼容性好:如果列不存在,自动跳过,不影响主流程
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:1.0
|
||||
**创建时间**:2025-11-05
|
||||
**功能状态**:✅ 已实现
|
||||
|
||||
@@ -537,23 +537,35 @@ public class TencentDocController extends BaseController {
|
||||
}
|
||||
|
||||
// 自动识别列位置(如果未指定)
|
||||
Integer arrangedColumn = null; // "是否安排"列
|
||||
Integer markColumn = null; // "标记"列
|
||||
|
||||
if (orderNoColumn == null || logisticsLinkColumn == null) {
|
||||
JSONArray headerRowData = headerValues.getJSONArray(0);
|
||||
if (headerRowData == null || headerRowData.isEmpty()) {
|
||||
return AjaxResult.error("无法识别表头,请手动指定列位置");
|
||||
}
|
||||
|
||||
// 查找单号列和物流链接列
|
||||
// 查找所有相关列
|
||||
for (int i = 0; i < headerRowData.size(); i++) {
|
||||
String cellValue = headerRowData.getString(i);
|
||||
if (cellValue != null) {
|
||||
String cellValueLower = cellValue.toLowerCase().trim();
|
||||
if (orderNoColumn == null && (cellValueLower.contains("单号") || cellValueLower.contains("order"))) {
|
||||
String cellValueTrim = cellValue.trim();
|
||||
if (orderNoColumn == null && cellValueTrim.contains("单号")) {
|
||||
orderNoColumn = i;
|
||||
log.info("识别到 '单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (logisticsLinkColumn == null && (cellValueLower.contains("物流链接") ||
|
||||
(cellValueLower.contains("物流") && cellValueLower.contains("链接")))) {
|
||||
if (logisticsLinkColumn == null && (cellValueTrim.contains("物流单号") || cellValueTrim.contains("物流链接"))) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("识别到 '物流单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (arrangedColumn == null && cellValueTrim.contains("是否安排")) {
|
||||
arrangedColumn = i;
|
||||
log.info("识别到 '是否安排' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (markColumn == null && cellValueTrim.contains("标记")) {
|
||||
markColumn = i;
|
||||
log.info("识别到 '标记' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -675,6 +687,9 @@ public class TencentDocController extends BaseController {
|
||||
|
||||
// 批量更新表格
|
||||
if (!updates.isEmpty()) {
|
||||
// 获取今天的日期,格式:yyMMdd(如:251105)
|
||||
String today = new java.text.SimpleDateFormat("yyMMdd").format(new java.util.Date());
|
||||
|
||||
// 将更新按行分组,批量写入
|
||||
Map<Integer, JSONObject> rowUpdates = new java.util.HashMap<>();
|
||||
for (int i = 0; i < updates.size(); i++) {
|
||||
@@ -683,31 +698,43 @@ public class TencentDocController extends BaseController {
|
||||
rowUpdates.put(row, update);
|
||||
}
|
||||
|
||||
// 批量写入(每行单独写入,因为腾讯文档API可能不支持批量更新不同行)
|
||||
// 批量写入(每行单独写入,同时更新多个字段)
|
||||
int successUpdates = 0;
|
||||
for (Map.Entry<Integer, JSONObject> entry : rowUpdates.entrySet()) {
|
||||
try {
|
||||
int row = entry.getKey();
|
||||
JSONObject update = entry.getValue();
|
||||
String logisticsLink = update.getString("logisticsLink");
|
||||
String orderNo = update.getString("orderNo");
|
||||
|
||||
// 计算列字母(A, B, C...)
|
||||
String columnLetter = getColumnLetter(logisticsLinkColumn);
|
||||
String cellRange = columnLetter + row;
|
||||
// 使用 batchUpdate 一次性更新多个字段
|
||||
JSONArray requests = new JSONArray();
|
||||
|
||||
// 构建写入数据(二维数组格式)
|
||||
JSONArray writeValues = new JSONArray();
|
||||
JSONArray writeRow = new JSONArray();
|
||||
writeRow.add(logisticsLink);
|
||||
writeValues.add(writeRow);
|
||||
// 1. 更新物流单号
|
||||
requests.add(buildUpdateCellRequest(sheetId, row - 1, logisticsLinkColumn, logisticsLink));
|
||||
|
||||
// 写入单个单元格
|
||||
tencentDocService.writeSheetData(accessToken, fileId, sheetId, cellRange, writeValues);
|
||||
// 2. 更新"是否安排"列(如果存在)
|
||||
if (arrangedColumn != null) {
|
||||
requests.add(buildUpdateCellRequest(sheetId, row - 1, arrangedColumn, "2"));
|
||||
}
|
||||
|
||||
// 3. 更新"标记"列(如果存在)
|
||||
if (markColumn != null) {
|
||||
requests.add(buildUpdateCellRequest(sheetId, row - 1, markColumn, today));
|
||||
}
|
||||
|
||||
// 构建完整的 batchUpdate 请求体
|
||||
JSONObject batchUpdateBody = new JSONObject();
|
||||
batchUpdateBody.put("requests", requests);
|
||||
|
||||
// 调用 batchUpdate API
|
||||
tencentDocService.batchUpdate(accessToken, fileId, batchUpdateBody);
|
||||
successUpdates++;
|
||||
|
||||
log.info("成功写入物流链接 - 单元格: {}, 单号: {}, 物流链接: {}", cellRange, update.getString("orderNo"), logisticsLink);
|
||||
log.info("成功写入数据 - 行: {}, 单号: {}, 物流链接: {}, 是否安排: 2, 标记: {}",
|
||||
row, orderNo, logisticsLink, today);
|
||||
} catch (Exception e) {
|
||||
log.error("写入物流链接失败 - 行: {}", entry.getKey(), e);
|
||||
log.error("写入数据失败 - 行: {}", entry.getKey(), e);
|
||||
errorCount++;
|
||||
}
|
||||
|
||||
@@ -748,6 +775,50 @@ public class TencentDocController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建单个单元格的更新请求(用于 batchUpdate)
|
||||
*
|
||||
* @param sheetId 工作表ID
|
||||
* @param rowIndex 行索引(从0开始)
|
||||
* @param columnIndex 列索引(从0开始)
|
||||
* @param value 要写入的值
|
||||
* @return updateRangeRequest 对象
|
||||
*/
|
||||
private JSONObject buildUpdateCellRequest(String sheetId, int rowIndex, int columnIndex, String value) {
|
||||
// 构建 updateRangeRequest
|
||||
JSONObject updateRangeRequest = new JSONObject();
|
||||
updateRangeRequest.put("sheetId", sheetId);
|
||||
|
||||
// 构建 gridData
|
||||
JSONObject gridData = new JSONObject();
|
||||
gridData.put("startRow", rowIndex);
|
||||
gridData.put("startColumn", columnIndex);
|
||||
|
||||
// 构建 rows 数组
|
||||
JSONArray rows = new JSONArray();
|
||||
JSONObject rowData = new JSONObject();
|
||||
JSONArray cellValues = new JSONArray();
|
||||
|
||||
// 构建单元格数据
|
||||
JSONObject cellData = new JSONObject();
|
||||
JSONObject cellValue = new JSONObject();
|
||||
cellValue.put("text", value);
|
||||
cellData.put("cellValue", cellValue);
|
||||
cellValues.add(cellData);
|
||||
|
||||
rowData.put("values", cellValues);
|
||||
rows.add(rowData);
|
||||
gridData.put("rows", rows);
|
||||
|
||||
updateRangeRequest.put("gridData", gridData);
|
||||
|
||||
// 包装为 request 对象
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("updateRangeRequest", updateRangeRequest);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将列索引转换为Excel列字母(0->A, 1->B, ..., 25->Z, 26->AA, ...)
|
||||
*/
|
||||
|
||||
@@ -105,5 +105,15 @@ public interface ITencentDocService {
|
||||
* @return 用户信息
|
||||
*/
|
||||
JSONObject getUserInfo(String accessToken);
|
||||
|
||||
/**
|
||||
* 批量更新表格(batchUpdate API)
|
||||
*
|
||||
* @param accessToken 访问令牌
|
||||
* @param fileId 文件ID
|
||||
* @param requestBody batchUpdate 请求体,包含 requests 数组
|
||||
* @return 更新结果
|
||||
*/
|
||||
JSONObject batchUpdate(String accessToken, String fileId, JSONObject requestBody);
|
||||
}
|
||||
|
||||
|
||||
@@ -403,5 +403,33 @@ public class TencentDocServiceImpl implements ITencentDocService {
|
||||
throw new RuntimeException("获取用户信息失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject batchUpdate(String accessToken, String fileId, JSONObject requestBody) {
|
||||
try {
|
||||
// 获取用户信息(包含Open-Id)
|
||||
JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken);
|
||||
JSONObject data = userInfo.getJSONObject("data");
|
||||
if (data == null) {
|
||||
throw new RuntimeException("无法获取用户数据,请检查Access Token是否有效");
|
||||
}
|
||||
String openId = data.getString("openID");
|
||||
if (openId == null || openId.isEmpty()) {
|
||||
throw new RuntimeException("无法获取Open-Id,请检查Access Token是否有效");
|
||||
}
|
||||
|
||||
return TencentDocApiUtil.batchUpdate(
|
||||
accessToken,
|
||||
tencentDocConfig.getAppId(),
|
||||
openId,
|
||||
fileId,
|
||||
requestBody,
|
||||
tencentDocConfig.getApiBaseUrl()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("批量更新表格失败 - fileId: {}", fileId, e);
|
||||
throw new RuntimeException("批量更新表格失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public class LogisticsScanTask {
|
||||
* 定时任务:每1小时执行一次
|
||||
* Cron表达式:0 0 * * * ? 表示每小时的第0分钟执行
|
||||
*/
|
||||
@Scheduled(cron = "0 0 * * * ?")
|
||||
@Scheduled(cron = "0 */30 * * * ?")
|
||||
public void scanAndFetchLogistics() {
|
||||
logger.info("========== 开始执行物流信息扫描定时任务 ==========");
|
||||
|
||||
|
||||
@@ -435,6 +435,28 @@ public class TencentDocApiUtil {
|
||||
return callApi(accessToken, appId, openId, apiUrl, "POST", requestBody.toJSONString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新表格(batchUpdate API)
|
||||
* 根据官方文档:https://docs.qq.com/open/document/app/openapi/v3/sheet/batchupdate/update.html
|
||||
*
|
||||
* @param accessToken 访问令牌
|
||||
* @param appId 应用ID
|
||||
* @param openId 开放平台用户ID
|
||||
* @param fileId 文件ID
|
||||
* @param requestBody 请求体,包含 requests 数组
|
||||
* @param apiBaseUrl API基础地址
|
||||
* @return 更新结果
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 A1 表示法为行列索引
|
||||
* 例如:
|
||||
|
||||
Reference in New Issue
Block a user