419 lines
16 KiB
Markdown
419 lines
16 KiB
Markdown
# 腾讯文档物流链接自动填充 - 实现逻辑说明
|
||
|
||
## 功能概述
|
||
|
||
自动从数据库中查询订单的物流链接,并填充到腾讯文档对应的单元格中。
|
||
|
||
---
|
||
|
||
## 📋 完整实现逻辑
|
||
|
||
### 第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` 字段查询订单
|
||
|