262 lines
7.5 KiB
Markdown
262 lines
7.5 KiB
Markdown
# 从Status字段提取手机号码功能说明
|
||
|
||
## 功能概述
|
||
|
||
在批量同步物流链接到腾讯文档时,系统会自动从订单的 `status` 字段中提取手机号码,并写入到腾讯文档的"下单电话"列。
|
||
|
||
> **注意:** 手机号码存储在 `status` 字段,不是 `remark` 字段。
|
||
|
||
## 实现原理
|
||
|
||
### 1. 列识别
|
||
|
||
系统在读取表头时,会自动识别以下列名:
|
||
- `下单电话`
|
||
- `电话`
|
||
- `手机`
|
||
|
||
任何包含以上关键词的列都会被识别为"下单电话"列。
|
||
|
||
### 2. 手机号码提取
|
||
|
||
从订单的 `status`(状态)字段中提取手机号码:
|
||
|
||
**提取规则:**
|
||
- 自动移除status字段中的空格、横线、括号等分隔符
|
||
- 使用正则表达式匹配11位手机号码(1开头的11位数字)
|
||
- 支持格式示例:
|
||
```
|
||
138 0013 8000
|
||
138-0013-8000
|
||
(138)00138000
|
||
13800138000
|
||
```
|
||
|
||
**正则表达式:** `1[3-9]\d{9}`
|
||
|
||
**匹配规则:**
|
||
- 第1位必须是 `1`
|
||
- 第2位必须是 `3-9`
|
||
- 后面9位是任意数字 `0-9`
|
||
|
||
### 3. 写入逻辑
|
||
|
||
在批量同步时,如果同时满足以下条件,会写入手机号码:
|
||
1. ✅ 表头中识别到了"下单电话"列
|
||
2. ✅ 从订单备注中成功提取到手机号码
|
||
3. ✅ 订单有物流链接需要同步
|
||
|
||
写入时使用 `batchUpdate` API,一次性更新多个字段:
|
||
1. 物流单号(超链接类型)
|
||
2. **下单电话(普通文本)** ← 新增
|
||
3. 是否安排(值为"2")
|
||
4. 标记(当前日期,格式:251106)
|
||
|
||
## 代码实现
|
||
|
||
### 关键方法
|
||
|
||
#### `extractPhoneFromRemark(String remark)`
|
||
|
||
```java
|
||
/**
|
||
* 从备注中提取手机号码
|
||
* 支持11位手机号码,可能包含空格、横线等分隔符
|
||
*
|
||
* @param remark 备注信息
|
||
* @return 提取到的手机号码,如果没有则返回null
|
||
*/
|
||
private String extractPhoneFromRemark(String remark) {
|
||
if (remark == null || remark.trim().isEmpty()) {
|
||
return null;
|
||
}
|
||
|
||
// 移除所有空格、横线、括号等分隔符
|
||
String cleanedRemark = remark.replaceAll("[\\s\\-\\(\\)\\[\\]()\\【\\】]", "");
|
||
|
||
// 匹配11位手机号码(1开头的11位数字)
|
||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("1[3-9]\\d{9}");
|
||
java.util.regex.Matcher matcher = pattern.matcher(cleanedRemark);
|
||
|
||
if (matcher.find()) {
|
||
String phone = matcher.group();
|
||
log.debug("从备注中提取到手机号码: {}", phone);
|
||
return phone;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
```
|
||
|
||
### 使用位置
|
||
|
||
**`TencentDocController.fillLogisticsByOrderNo`** - 批量同步方法
|
||
|
||
1. **列识别阶段**(第1003-1008行):
|
||
```java
|
||
// 识别"下单电话"列(可选)
|
||
if (phoneColumn == null && (cellValueTrim.contains("下单电话")
|
||
|| cellValueTrim.contains("电话")
|
||
|| cellValueTrim.contains("手机"))) {
|
||
phoneColumn = i;
|
||
log.info("✓ 识别到 '下单电话' 列:第 {} 列(索引{})", i + 1, i);
|
||
}
|
||
```
|
||
|
||
2. **数据处理阶段**(第1188-1195行):
|
||
```java
|
||
// 从status字段中提取手机号码
|
||
String phone = null;
|
||
if (phoneColumn != null) {
|
||
phone = extractPhoneFromRemark(order.getStatus());
|
||
if (phone != null) {
|
||
log.info("✓ 从status字段提取手机号码 - 单号: {}, 手机号: {}", orderNo, phone);
|
||
}
|
||
}
|
||
```
|
||
|
||
3. **构建更新请求**(第1201-1205行):
|
||
```java
|
||
// 如果找到手机号码,也添加到更新中
|
||
if (phone != null && phoneColumn != null) {
|
||
update.put("phone", phone);
|
||
update.put("phoneColumn", phoneColumn);
|
||
}
|
||
```
|
||
|
||
4. **写入腾讯文档**(第1294-1300行):
|
||
```java
|
||
// 2. 更新"下单电话"列(如果存在且提取到了手机号码)
|
||
String phone = update.getString("phone");
|
||
Integer phoneCol = update.getInteger("phoneColumn");
|
||
if (phone != null && phoneCol != null) {
|
||
requests.add(buildUpdateCellRequest(sheetId, row - 1, phoneCol, phone, false));
|
||
log.info("✓ 准备写入手机号码 - 单号: {}, 手机号: {}, 行: {}, 列: {}",
|
||
expectedOrderNo, phone, row, phoneCol);
|
||
}
|
||
```
|
||
|
||
## 日志输出
|
||
|
||
### 成功提取手机号码
|
||
|
||
```
|
||
✓ 从status字段提取手机号码 - 单号: JY2025110601, 手机号: 13800138000
|
||
✓ 准备写入手机号码 - 单号: JY2025110601, 手机号: 13800138000, 行: 3, 列: 6
|
||
✓ 写入成功 - 行: 3, 单号: JY2025110601, 物流链接: https://3.cn/xxx, 手机号: 13800138000
|
||
```
|
||
|
||
### 未找到手机号码
|
||
|
||
```
|
||
找到订单物流链接 - 单号: JY2025110602, 物流链接: https://3.cn/xxx, 手机号: 无, 行号: 4, 已推送: 否
|
||
✓ 写入成功 - 行: 4, 单号: JY2025110602, 物流链接: https://3.cn/xxx
|
||
```
|
||
|
||
### 未识别到"下单电话"列
|
||
|
||
```
|
||
未找到'下单电话'列,将跳过该字段的更新
|
||
列位置识别完成 - 单号: 2, 物流单号: 12, 是否安排: null, 标记: 14, 下单电话: null
|
||
```
|
||
|
||
## 使用示例
|
||
|
||
### 订单Status字段示例
|
||
|
||
| Status内容 | 提取结果 | 说明 |
|
||
|---------|---------|------|
|
||
| `联系电话:138 0013 8000` | `13800138000` | ✅ 成功提取 |
|
||
| `手机号138-0013-8000` | `13800138000` | ✅ 成功提取 |
|
||
| `电话:(138)00138000` | `13800138000` | ✅ 成功提取 |
|
||
| `13800138000 张三` | `13800138000` | ✅ 成功提取 |
|
||
| `17703916233` | `17703916233` | ✅ 成功提取 |
|
||
| `无电话` | `null` | ❌ 未提取到 |
|
||
| `12345678901` | `null` | ❌ 不符合规则(不是1开头) |
|
||
| `1280013800` | `null` | ❌ 不符合规则(第2位不是3-9) |
|
||
|
||
### 腾讯文档表头示例
|
||
|
||
支持的表头名称(包含即可识别):
|
||
- ✅ `下单电话`
|
||
- ✅ `电话`
|
||
- ✅ `手机`
|
||
- ✅ `手机号`
|
||
- ✅ `联系电话`
|
||
- ✅ `客户电话`
|
||
|
||
## 兼容性
|
||
|
||
### 向后兼容
|
||
|
||
- ✅ 如果表头中**没有**"下单电话"列,功能自动跳过,不影响其他字段的同步
|
||
- ✅ 如果订单status字段中**没有**手机号码,功能自动跳过,不影响其他字段的同步
|
||
- ✅ 不影响现有的物流链接、是否安排、标记字段的同步
|
||
|
||
### 可选性
|
||
|
||
此功能是**完全可选**的:
|
||
1. 不需要在表头中添加"下单电话"列
|
||
2. 订单status字段可以不包含手机号码
|
||
3. 功能会自动识别和适配
|
||
|
||
## 测试建议
|
||
|
||
### 测试场景
|
||
|
||
1. **正常场景**
|
||
- 表头包含"下单电话"列
|
||
- 订单status字段包含手机号码
|
||
- 预期:手机号码正确写入
|
||
|
||
2. **无电话列场景**
|
||
- 表头不包含"下单电话"列
|
||
- 预期:其他字段正常同步,手机号码跳过
|
||
|
||
3. **无手机号场景**
|
||
- 表头包含"下单电话"列
|
||
- 订单status字段不包含手机号码
|
||
- 预期:其他字段正常同步,手机号码列为空
|
||
|
||
4. **多种格式场景**
|
||
- 测试不同格式的手机号码(带空格、横线、括号等)
|
||
- 预期:都能正确提取
|
||
|
||
### 测试步骤
|
||
|
||
1. 在腾讯文档表头添加"下单电话"列(或"电话"、"手机")
|
||
2. 确保订单的status字段包含手机号码(例如:17703916233)
|
||
3. 点击"批量同步物流"按钮
|
||
4. 查看后端日志,确认提取和写入成功
|
||
5. 查看腾讯文档,确认手机号码正确显示在"下单电话"列
|
||
|
||
## 未来优化建议
|
||
|
||
1. **支持更多手机号格式**
|
||
- 国际号码(+86)
|
||
- 固定电话(区号+号码)
|
||
|
||
2. **支持多个手机号**
|
||
- 从备注中提取多个手机号码
|
||
- 用逗号或分号分隔
|
||
|
||
3. **手机号验证**
|
||
- 验证号码段有效性(如:135、138等)
|
||
- 提示无效号码
|
||
|
||
4. **手机号脱敏**
|
||
- 日志中对手机号进行脱敏显示
|
||
- 如:138****8000
|
||
|
||
## 相关文件
|
||
|
||
- **Controller**: `TencentDocController.java`
|
||
- **方法**: `fillLogisticsByOrderNo()`, `extractPhoneFromRemark()`
|
||
- **API**: 腾讯文档 `batchUpdate` API
|
||
|
||
---
|
||
|
||
**最后更新时间**: 2025-11-06
|
||
**版本**: v1.0
|
||
|