16 KiB
16 KiB
腾讯文档物流链接自动填充 - 实现逻辑说明
功能概述
自动从数据库中查询订单的物流链接,并填充到腾讯文档对应的单元格中。
📋 完整实现逻辑
第1步:读取表头(识别列位置)
// 读取 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步:读取数据行
// 计算读取范围
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"
🔍 关键字段说明
表格中的"单号"(草号)
- 表头名称:草号
- 列索引:2(C列)
- 示例值:
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);
修复内容:
- ✅ 在
IJDOrderService接口中添加方法 - ✅ 在
JDOrderServiceImpl实现类中实现方法 - ✅ 在
JDOrderMapper接口中添加方法声明 - ✅ 在
JDOrderMapper.xml中添加SQL查询 - ✅ 在
TencentDocController中更新调用
修改的文件:
ruoyi-system/src/main/java/com/ruoyi/jarvis/service/IJDOrderService.javaruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/JDOrderServiceImpl.javaruoyi-system/src/main/java/com/ruoyi/jarvis/mapper/JDOrderMapper.javaruoyi-system/src/main/resources/mapper/jarvis/JDOrderMapper.xmlruoyi-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列(索引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.0
创建时间:2025-11-05
修改内容:使用 thirdPartyOrderNo 字段查询订单