Files
ruoyi-java/doc/腾讯文档物流链接自动填充-实现逻辑说明.md
2025-11-06 10:57:22 +08:00

16 KiB
Raw Blame History

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

功能概述

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


📋 完整实现逻辑

第1步读取表头识别列位置

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

目的

  • 自动识别"单号"列的位置(orderNoColumn
  • 自动识别"物流链接"列的位置(logisticsLinkColumn

表头示例

| A列  | B列 | C列 | D列 | ... | M列       | N列  |
|------|-----|-----|-----|-----|-----------|------|
| 日期 | 公司| 草号| 型号| ... | 物流单号  | 标记 |

自动识别结果:

  • 草号列(单号列):索引 2C列
  • 物流单号列:索引 12M列

第2步读取数据行

// 计算读取范围
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步遍历每一行匹配订单并收集需要更新的数据

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步批量写入物流链接

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"

🔍 关键字段说明

表格中的"单号"(草号)

  • 表头名称:草号
  • 列索引2C列
  • 示例值JY20251032904
  • 用途:用于在数据库中查询订单

数据库中的"第三方单号"

  • 字段名third_party_order_no
  • Java 属性thirdPartyOrderNo
  • 对应关系:表格中的"草号" = 数据库中的"第三方单号"

数据库查询SQL

SELECT * FROM jd_order 
WHERE third_party_order_no = #{thirdPartyOrderNo}
LIMIT 1

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 调用参数

请求参数

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

参数说明

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

响应结果

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

结果说明

  • startRow:本次处理的起始行
  • endRow:本次处理的结束行
  • filledCount:成功填充的数量
  • skippedCount:跳过的数量(已有值或单号为空)
  • errorCount:错误数量(未找到订单或物流链接)

🎯 修改说明

修改前:使用 remark 字段查询

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

问题

  • remark 字段是"内部单号"
  • 表格中的"草号"对应的是"第三方单号"
  • 字段不匹配,查不到订单

修改后:使用 thirdPartyOrderNo 字段查询

// 正确:使用第三方单号查询
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自动识别列位置

POST /api/tencent-doc/fill-logistics

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

系统会自动识别:

  • 包含"单号"的列作为订单号列
  • 包含"物流"的列作为物流链接列

示例2手动指定列位置

POST /api/tencent-doc/fill-logistics

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

明确指定:

  • 单号列在第3列索引2C列
  • 物流链接列在第13列索引12M列

🚨 注意事项

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 字段查询订单