# 从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