# 物流链接自动填充 - 多字段更新功能

## ✅ 新功能说明

在成功匹配订单并写入物流链接的同时，自动更新以下三个字段：

| 字段 | 写入内容 | 说明 |
|------|----------|------|
| **物流单号** | 物流链接 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  
**功能状态**：✅ 已实现

