fix(address-edit): 修复地址编辑页粘贴文本智能识别问题

- 优化姓名匹配优先查找标签“收件人”等后面的名字,提升识别准确率
- 清理详细地址中标签文本,去除“收件人”“手机号码”“所在地区”“详细地址”等冗余字段
- 保留街道及详细地址完整信息,避免误删有效内容
- 类型定义中新增 country,调整 isDefault 类型为 boolean,增加 address 字段
- 使用 Python 测试验证解析效果,确保姓名、电话、省市区和详细地址准确提取
- 通过类型检查无误,提升代码健壮性和维护便利性
This commit is contained in:
2026-07-15 11:10:29 +08:00
parent 81324cbb82
commit 3955e64844
3 changed files with 48 additions and 7 deletions

View File

@@ -63,3 +63,18 @@
4. list.tsx `handleCloseOrder`:弹窗标题改为"确认取消订单"toast 改为"订单已取消" 4. list.tsx `handleCloseOrder`:弹窗标题改为"确认取消订单"toast 改为"订单已取消"
5. detail.tsx `getOrderDisplayStatus`:线下付款未确认时显示"待发货"蓝色subtitle 保留付款引导文案 5. detail.tsx `getOrderDisplayStatus`:线下付款未确认时显示"待发货"蓝色subtitle 保留付款引导文案
6. detail.tsx `getOrderPhase`:保留 `offline_pending` 阶段,底部按钮仍为"取消订单+联系客服"(未确认收款可取消,非退款) 6. detail.tsx `getOrderPhase`:保留 `offline_pending` 阶段,底部按钮仍为"取消订单+联系客服"(未确认收款可取消,非退款)
## 修复地址编辑页智能识别 bug
- 文件:`src/pages/user/address-edit.tsx`
- 问题:粘贴带标签的地址文本(如「收件人: 赵忠林 / 手机号码: 137... / 所在地区: 广西... / 详细地址: 大学东路...」)识别后:
1. 姓名识别失败(之前只看文本开头的 2-4 个汉字,姓名不在开头)
2. 详细地址保留了「收件人」「手机号码」「所在地区」「详细地址」等标签文字
- 修复 `parseAddressText`
1. 姓名优先匹配 `(?:收件人|收货人|姓名|联系人)[:]\s*([\u4e00-\u9fa5]{2,4})`,找不到再回退到 `^[\u4e00-\u9fa5]{2,4}`
2. 详细地址提取前先 strip 标签文字(收件人/手机号/所在地区/详细地址 + 中英冒号),再 strip 省市区,最后 strip 零散标签
- 验证:用 Python 模拟Python 是用 JS 同款正则+RegionData解析截图中的输入
- name: 赵忠林 ✓
- phone: 13737128880 ✓
- province/city/region: 广西壮族自治区/南宁市/西乡塘区 ✓
- address: 西乡塘街道大学东路9号瀚林御景3栋1单元1101号房 ✓(街道+详细地址完整保留)
- 项目 type-check (`npx tsc --noEmit`) 无报错

View File

@@ -4,6 +4,7 @@ export interface ShopUserAddress {
userId?: number; userId?: number;
name?: string; // 收货人姓名 name?: string; // 收货人姓名
phone?: string; // 收货人电话 phone?: string; // 收货人电话
country?: string; // 国家
province?: string; // 省份 province?: string; // 省份
city?: string; // 城市 city?: string; // 城市
district?: string; // 区县 district?: string; // 区县
@@ -11,7 +12,8 @@ export interface ShopUserAddress {
detail?: string; // 详细地址 detail?: string; // 详细地址
lng?: string; // 经度 lng?: string; // 经度
lat?: string; // 纬度 lat?: string; // 纬度
isDefault?: number; // 是否默认 0-否 1-是 isDefault?: boolean; // 是否默认 0-否 1-是
createTime?: string; createTime?: string;
updateTime?: string; updateTime?: string;
address?: string;
} }

View File

@@ -101,6 +101,7 @@ const AddressEditPage: React.FC = () => {
const [formData, setFormData] = useState<Partial<ShopUserAddress>>({ const [formData, setFormData] = useState<Partial<ShopUserAddress>>({
name: '', name: '',
phone: '', phone: '',
country: '',
province: '', province: '',
city: '', city: '',
region: '', region: '',
@@ -148,15 +149,22 @@ const AddressEditPage: React.FC = () => {
const parseAddressText = (text: string) => { const parseAddressText = (text: string) => {
const result: any = {} const result: any = {}
// 手机号正则 // 手机号正则11 位国内手机号)
const phoneRegex = /1[3-9]\d{9}/ const phoneRegex = /1[3-9]\d{9}/
const phoneMatch = text.match(phoneRegex) const phoneMatch = text.match(phoneRegex)
if (phoneMatch) result.phone = phoneMatch[0] if (phoneMatch) result.phone = phoneMatch[0]
// 姓名正则2-4个中文字符,通常在开头) // 姓名正则:优先匹配“收件人/收货人/姓名/联系人:”后面的 2-4 个中文字符
const nameWithPrefixRegex = /(?:收件人|收货人|姓名|联系人)[:]\s*([\u4e00-\u9fa5]{2,4})/
const nameWithPrefixMatch = text.match(nameWithPrefixRegex)
if (nameWithPrefixMatch) {
result.name = nameWithPrefixMatch[1]
} else {
// 兜底:文本开头 2-4 个中文字符
const nameRegex = /^[\u4e00-\u9fa5]{2,4}/ const nameRegex = /^[\u4e00-\u9fa5]{2,4}/
const nameMatch = text.match(nameRegex) const nameMatch = text.match(nameRegex)
if (nameMatch) result.name = nameMatch[0] if (nameMatch) result.name = nameMatch[0]
}
// 省市区识别 // 省市区识别
const regionResult = parseRegion(text) const regionResult = parseRegion(text)
@@ -166,13 +174,29 @@ const AddressEditPage: React.FC = () => {
result.region = regionResult.region result.region = regionResult.region
} }
// 详细地址提取 // 详细地址提取:先把常见的标签字段和已知字段去掉,再清洗标点
let addressText = text let addressText = text
// 去除已提取的姓名、手机号
if (result.name) addressText = addressText.replace(result.name, '') if (result.name) addressText = addressText.replace(result.name, '')
if (result.phone) addressText = addressText.replace(result.phone, '') if (result.phone) addressText = addressText.replace(result.phone, '')
// 去除常见标签文案(如“收件人:”、“手机号码:”、“所在地区:”、“详细地址:”)
addressText = addressText
.replace(/(?:收件人|收货人|姓名|联系人)[:]\s*/g, '')
.replace(/(?:手机号码|手机号|电话|联系电话)[:]\s*/g, '')
.replace(/(?:所在地区|地区|省市区)[:]\s*/g, '')
.replace(/(?:详细地址|地址|街道)[:]\s*/g, '')
// 去除已识别出的省市区
if (result.province) addressText = addressText.replace(result.province, '') if (result.province) addressText = addressText.replace(result.province, '')
if (result.city) addressText = addressText.replace(result.city, '') if (result.city) addressText = addressText.replace(result.city, '')
if (result.region) addressText = addressText.replace(result.region, '') if (result.region) addressText = addressText.replace(result.region, '')
// 去除零散的标签关键字(如“手机号码”、“所在地区”、“详细地址”本身)
addressText = addressText
.replace(/(?:收件人|收货人|手机号码|手机号|所在地区|详细地址)/g, '')
result.address = addressText.replace(/[,。\s]+/g, '').trim() result.address = addressText.replace(/[,。\s]+/g, '').trim()
return result return result