# 腾讯文档物流链接自动填充 - 实现逻辑说明

## 功能概述

自动从数据库中查询订单的物流链接，并填充到腾讯文档对应的单元格中。

---

## 📋 完整实现逻辑

### 第1步：读取表头（识别列位置）

```java
// 读取 headerRow 行（默认第2行）
String headerRange = "A2:Z2";
JSONObject headerData = tencentDocService.readSheetData(accessToken, fileId, sheetId, headerRange);
```

**目的**：
- 自动识别"单号"列的位置（`orderNoColumn`）
- 自动识别"物流链接"列的位置（`logisticsLinkColumn`）

**表头示例**：
```
| A列  | B列 | C列 | D列 | ... | M列       | N列  |
|------|-----|-----|-----|-----|-----------|------|
| 日期 | 公司| 草号| 型号| ... | 物流单号  | 标记 |
```

自动识别结果：
- 草号列（单号列）：索引 2（C列）
- 物流单号列：索引 12（M列）

---

### 第2步：读取数据行

```java
// 计算读取范围
int startRow = headerRow + 1;  // 表头下一行开始
int endRow = startRow + 200;    // 每次最多读取200行

String range = "A3:Z203";  // 从第3行到第203行
JSONObject sheetData = tencentDocService.readSheetData(accessToken, fileId, sheetId, range);
```

**数据示例**：
```
| A列    | B列 | C列            | ... | M列             | N列  |
|--------|-----|----------------|-----|-----------------|------|
| 3月10日|     | JY20251032904  | ... | (空)            | 是   |
| 3月10日|     | JY20250309184  | ... | 6649902864      | 是   |
| 3月10日|     | JY20250309143  | ... | (空)            | 是   |
```

---

### 第3步：遍历每一行，匹配订单并收集需要更新的数据

```java
for (int i = 0; i < values.size(); i++) {
    JSONArray row = values.getJSONArray(i);
    
    // 1. 获取单号（草号列）
    String orderNo = row.getString(orderNoColumn);  // 例如：JY20251032904
    
    // 2. 检查是否为空
    if (orderNo == null || orderNo.trim().isEmpty()) {
        skippedCount++;  // 跳过空单号
        continue;
    }
    
    // 3. 检查物流链接列是否已有值
    String existingLogisticsLink = row.getString(logisticsLinkColumn);
    if (existingLogisticsLink != null && !existingLogisticsLink.trim().isEmpty()) {
        skippedCount++;  // 已有物流链接，跳过
        continue;
    }
    
    // 4. 从数据库查询订单（使用第三方单号查询）
    JDOrder order = jdOrderService.selectJDOrderByThirdPartyOrderNo(orderNo);
    
    // 5. 检查是否找到订单且有物流链接
    if (order != null && order.getLogisticsLink() != null && !order.getLogisticsLink().trim().isEmpty()) {
        String logisticsLink = order.getLogisticsLink().trim();
        
        // 6. 记录需要更新的信息
        updates.add({
            "row": excelRow,           // 行号（Excel行号，如3表示第3行）
            "column": logisticsLinkColumn,  // 列索引（如12表示M列）
            "orderNo": orderNo,        // 单号
            "logisticsLink": logisticsLink  // 物流链接
        });
        
        filledCount++;
    } else {
        errorCount++;  // 未找到订单或物流链接为空
    }
}
```

**处理结果示例**：
```
找到3个需要更新的单元格：
  - M3: 订单号 JY20251032904 → 物流链接 6649906880
  - M5: 订单号 JY20250309143 → 物流链接 6649914494
  - M7: 订单号 JY20250307138 → 物流链接 6649909460

跳过2个已有物流链接的行
跳过1个单号为空的行
找不到物流链接的订单：0个
```

---

### 第4步：批量写入物流链接

```java
for (JSONObject update : updates) {
    int row = update.getIntValue("row");              // 例如：3
    int column = update.getIntValue("column");        // 例如：12
    String logisticsLink = update.getString("logisticsLink");
    
    // 1. 计算列字母（0→A, 1→B, ..., 12→M）
    String columnLetter = getColumnLetter(column);    // 12 → "M"
    
    // 2. 构建单元格地址
    String cellRange = columnLetter + row;            // "M3"
    
    // 3. 构建写入数据（二维数组格式）
    Object[][] writeData = {{logisticsLink}};
    
    // 4. 写入单个单元格
    tencentDocService.writeSheetData(accessToken, fileId, sheetId, cellRange, writeData);
    
    // 5. 延迟100ms（避免API限流）
    Thread.sleep(100);
}
```

**写入示例**：
```
写入 M3 单元格 = "6649906880"
写入 M5 单元格 = "6649914494"
写入 M7 单元格 = "6649909460"
```

---

## 🔍 关键字段说明

### 表格中的"单号"（草号）
- **表头名称**：草号
- **列索引**：2（C列）
- **示例值**：`JY20251032904`
- **用途**：用于在数据库中查询订单

### 数据库中的"第三方单号"
- **字段名**：`third_party_order_no`
- **Java 属性**：`thirdPartyOrderNo`
- **对应关系**：表格中的"草号" = 数据库中的"第三方单号"

**数据库查询SQL**：
```sql
SELECT * FROM jd_order 
WHERE third_party_order_no = #{thirdPartyOrderNo}
LIMIT 1
```

**Java 调用**：
```java
// 根据第三方单号查询订单
JDOrder order = jdOrderService.selectJDOrderByThirdPartyOrderNo(orderNo);
```

---

## 📊 完整流程图

```
┌─────────────────────────────────────────────────────────────────┐
│ 1. 读取表头（第2行）                                             │
│    识别列位置：单号列、物流链接列                                │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│ 2. 读取数据行（第3行 ~ 第203行，200行）                         │
│    range: A3:Z203                                               │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│ 3. 遍历每一行                                                   │
├─────────────────────────────────────────────────────────────────┤
│   ┌─────────────────────────────────────────────────┐          │
│   │ 3.1 读取单号（草号列，C列）                      │          │
│   └──────────────┬──────────────────────────────────┘          │
│                  │                                              │
│                  ▼                                              │
│   ┌─────────────────────────────────────────────────┐          │
│   │ 3.2 单号为空？                                   │          │
│   │     是 → 跳过                                    │          │
│   │     否 → 继续                                    │          │
│   └──────────────┬──────────────────────────────────┘          │
│                  │                                              │
│                  ▼                                              │
│   ┌─────────────────────────────────────────────────┐          │
│   │ 3.3 物流链接列已有值？                           │          │
│   │     是 → 跳过                                    │          │
│   │     否 → 继续                                    │          │
│   └──────────────┬──────────────────────────────────┘          │
│                  │                                              │
│                  ▼                                              │
│   ┌─────────────────────────────────────────────────┐          │
│   │ 3.4 查询数据库                                   │          │
│   │     WHERE third_party_order_no = '单号'         │          │
│   └──────────────┬──────────────────────────────────┘          │
│                  │                                              │
│                  ▼                                              │
│   ┌─────────────────────────────────────────────────┐          │
│   │ 3.5 找到订单 且 有物流链接？                     │          │
│   │     是 → 记录到更新列表                          │          │
│   │     否 → 记录为错误                              │          │
│   └──────────────────────────────────────────────────┘          │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│ 4. 批量写入物流链接                                             │
├─────────────────────────────────────────────────────────────────┤
│   对于每个需要更新的单元格：                                     │
│   1. 计算单元格地址（如 M3）                                    │
│   2. 调用写入API                                                │
│   3. 延迟100ms（避免限流）                                      │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│ 5. 返回处理结果                                                 │
│    - 成功填充数量                                               │
│    - 跳过数量                                                   │
│    - 错误数量                                                   │
└─────────────────────────────────────────────────────────────────┘
```

---

## 🔧 API 调用参数

### 请求参数

```json
{
  "accessToken": "腾讯文档访问令牌",
  "fileId": "DUW50RUprWXh2TGJK",
  "sheetId": "BB08J2",
  "headerRow": 2,
  "orderNoColumn": 2,
  "logisticsLinkColumn": 12
}
```

**参数说明**：
- `accessToken`：必填，腾讯文档访问令牌
- `fileId`：必填，文件ID（从文档URL中获取）
- `sheetId`：必填，工作表ID（从URL的tab参数中获取）
- `headerRow`：可选，表头所在行号（默认1，但根据您的表格应该是2）
- `orderNoColumn`：可选，单号列索引（如果不提供则自动识别）
- `logisticsLinkColumn`：可选，物流链接列索引（如果不提供则自动识别）

### 响应结果

```json
{
  "msg": "物流链接填充成功",
  "code": 200,
  "data": {
    "startRow": 3,
    "endRow": 203,
    "lastMaxRow": null,
    "filledCount": 3,
    "skippedCount": 2,
    "errorCount": 0,
    "message": "成功填充3个物流链接"
  }
}
```

**结果说明**：
- `startRow`：本次处理的起始行
- `endRow`：本次处理的结束行
- `filledCount`：成功填充的数量
- `skippedCount`：跳过的数量（已有值或单号为空）
- `errorCount`：错误数量（未找到订单或物流链接）

---

## 🎯 修改说明

### 修改前：使用 `remark` 字段查询

```java
// 错误：使用内部单号查询
JDOrder order = jdOrderService.selectJDOrderByRemark(orderNo);
```

**问题**：
- `remark` 字段是"内部单号"
- 表格中的"草号"对应的是"第三方单号"
- 字段不匹配，查不到订单

### 修改后：使用 `thirdPartyOrderNo` 字段查询

```java
// 正确：使用第三方单号查询
JDOrder order = jdOrderService.selectJDOrderByThirdPartyOrderNo(orderNo);
```

**修复内容**：
1. ✅ 在 `IJDOrderService` 接口中添加方法
2. ✅ 在 `JDOrderServiceImpl` 实现类中实现方法
3. ✅ 在 `JDOrderMapper` 接口中添加方法声明
4. ✅ 在 `JDOrderMapper.xml` 中添加SQL查询
5. ✅ 在 `TencentDocController` 中更新调用

**修改的文件**：
- `ruoyi-system/src/main/java/com/ruoyi/jarvis/service/IJDOrderService.java`
- `ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/JDOrderServiceImpl.java`
- `ruoyi-system/src/main/java/com/ruoyi/jarvis/mapper/JDOrderMapper.java`
- `ruoyi-system/src/main/resources/mapper/jarvis/JDOrderMapper.xml`
- `ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java`

---

## 📝 使用示例

### 示例1：自动识别列位置

```bash
POST /api/tencent-doc/fill-logistics

{
  "accessToken": "YOUR_ACCESS_TOKEN",
  "fileId": "DUW50RUprWXh2TGJK",
  "sheetId": "BB08J2",
  "headerRow": 2
}
```

系统会自动识别：
- 包含"单号"的列作为订单号列
- 包含"物流"的列作为物流链接列

### 示例2：手动指定列位置

```bash
POST /api/tencent-doc/fill-logistics

{
  "accessToken": "YOUR_ACCESS_TOKEN",
  "fileId": "DUW50RUprWXh2TGJK",
  "sheetId": "BB08J2",
  "headerRow": 2,
  "orderNoColumn": 2,
  "logisticsLinkColumn": 12
}
```

明确指定：
- 单号列在第3列（索引2，C列）
- 物流链接列在第13列（索引12，M列）

---

## 🚨 注意事项

### 1. 行列索引从0开始

- 列索引：A列=0, B列=1, C列=2, ...
- 但行号是Excel行号（从1开始）

### 2. headerRow 参数

- 您的表格第1行是合并的标题
- 第2行才是真正的表头
- **必须设置 `headerRow: 2`**

### 3. 批量处理限制

- 每次最多处理200行
- 每次写入间隔100ms（避免API限流）
- 处理200行大约需要20-30秒

### 4. 数据库字段对应

| 表格列名 | 数据库字段名 | Java属性名 |
|---------|------------|-----------|
| 草号 | `third_party_order_no` | `thirdPartyOrderNo` |
| 物流单号 | `logistics_link` | `logisticsLink` |

---

## ✅ 功能特点

1. ✅ **自动识别列位置**：无需手动指定列索引
2. ✅ **智能跳过**：已有物流链接的行自动跳过
3. ✅ **批量处理**：一次处理多行数据
4. ✅ **增量处理**：记录上次处理位置，避免重复
5. ✅ **详细日志**：每一步都有日志记录
6. ✅ **错误处理**：完善的异常捕获和错误统计

---

**文档版本**：1.0  
**创建时间**：2025-11-05  
**修改内容**：使用 `thirdPartyOrderNo` 字段查询订单

