From a580cafe59a8f067cc6f011193952367beadcb2f Mon Sep 17 00:00:00 2001
From: Tevin <tingquanren@163.com>
Date: Fri, 22 Apr 2022 18:16:06 +0800
Subject: [PATCH] 地址组件,增加智能地址识别功能

---
 forms/chinaArea/SmartAddress.js |  226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 forms/chinaArea/index.js        |    4 
 2 files changed, 229 insertions(+), 1 deletions(-)

diff --git a/forms/chinaArea/SmartAddress.js b/forms/chinaArea/SmartAddress.js
new file mode 100644
index 0000000..750a6ac
--- /dev/null
+++ b/forms/chinaArea/SmartAddress.js
@@ -0,0 +1,226 @@
+/**
+ * SmartAddress
+ * @author Tevin
+ */
+
+import ChinaLocations from '@components/forms/chinaArea/ChinaLocations';
+import { Tools } from '@components/common/Tools';
+
+export class SmartAddress {
+    constructor() {
+        this.wordData = {};
+    }
+
+    parseWord(word, callback) {
+        if (!this._checkLength(word)) {
+            callback(false);
+            return;
+        }
+        this.wordData = {};
+        const wordArr = this._splitWord(word);
+        ChinaLocations.onReady(() => {
+            this._checkPhone(wordArr);
+            this._checkCompany(wordArr);
+            this._checkUser(wordArr);
+            this._checkAddress(wordArr);
+            if (Tools.isEmptyObject(this.wordData)) {
+                callback(false);
+            } else {
+                callback({ ...this.wordData });
+            }
+        });
+    }
+
+    _checkLength(word) {
+        if (!word || typeof word !== 'string') {
+            return false;
+        } else if (word.length < 8) {
+            return false;
+        } else if (word.length > 150) {
+            return false;
+        }
+        return true;
+    }
+
+    _splitWord(word) {
+        word = word.replace(/([::]) */g, '$1');  // 带类型名模式预处理
+        const splitReg = /[ \n\r…,.;?!'"()\[\],。;?!‘’“”()【】—|]/g;
+        const array = word.split(splitReg).filter(Boolean);
+        return array.map(item => {
+            const nextItem = { label: '', content: '' };
+            if (/[::]/.test(item)) {
+                const [label, content] = item.split(/[::]/g).filter(Boolean);
+                nextItem.label = label;
+                nextItem.content = content;
+            } else {
+                nextItem.content = item;
+            }
+            return nextItem;
+        });
+    }
+
+    _checkPhone(list) {
+        const phoneLabelReg = /^电话|联系电话|手机|手机号码$/;
+        const phoneReg = /^1[3456789]\d{9}$/;
+        const telReg = /\d{3.4}-\d{8}/;
+        for (let i = 0, item; (item = list[i]); i++) {
+            if (!item.content) {
+                continue;
+            }
+            if (item.label) {
+                if (phoneLabelReg.test(item.label)) {
+                    this.wordData.phone = item.content;
+                    if (this.wordData.phone.length === 13) {
+                        this.wordData.phone = this.wordData.phone.replace(/-/g, '');
+                    }
+                    list.splice(i, 1);
+                    break;
+                }
+            } else {
+                const phone = item.content.replace(/-/g, '');
+                if (phoneReg.test(phone)) {
+                    this.wordData.phone = phone;
+                    list.splice(i, 1);
+                    break;
+                } else if (telReg.test(item.content)) {
+                    this.wordData.phone = phone;
+                    list.splice(i, 1);
+                    break;
+                }
+            }
+        }
+    }
+
+    _checkCompany(list) {
+        const companyLabelReg = /公司|公司名称|客户|客户名称/;
+        const companyNameReg = /公司|厂|站|气|部$/;
+        for (let i = 0, item; (item = list[i]); i++) {
+            if (!item.content) {
+                continue;
+            }
+            if (item.label) {
+                if (companyLabelReg.test(item.label)) {
+                    this.wordData.company = item.content;
+                    list.splice(i, 1);
+                    break;
+                }
+            } else {
+                if (item.content.length > 5 && companyNameReg.test(item.content)) {
+                    this.wordData.company = item.content;
+                    list.splice(i, 1);
+                    break;
+                }
+            }
+        }
+    }
+
+    _checkUser(list) {
+        const userLabelReg = /姓名|联系人|收货人|收件人/;
+        const userReg = /^[\u4e00-\u9fa5]{2,3}$/;
+        for (let i = 0, item; (item = list[i]); i++) {
+            if (!item.content) {
+                continue;
+            }
+            if (item.label) {
+                if (userLabelReg.test(item.label)) {
+                    this.wordData.user = item.content;
+                    list.splice(i, 1);
+                    break;
+                }
+            } else {
+                if (userReg.test(item.content)) {
+                    this.wordData.user = item.content;
+                    list.splice(i, 1);
+                    break;
+                }
+            }
+        }
+    }
+
+    _checkAddress(list) {
+        const adrLabelReg = /地址|详细地址|公司地址|联系地址|地区|所在地区/;
+        for (let i = 0, item; (item = list[i]); i++) {
+            if (!item.content) {
+                continue;
+            }
+            if (item.label) {
+                if (adrLabelReg.test(item.label)) {
+                    this._parseAddress(item.content);
+                    list.splice(i, 1);
+                    break;
+                }
+            } else {
+                if (this._isAddress(item.content)) {
+                    this._parseAddress(item.content);
+                    list.splice(i, 1);
+                    break;
+                }
+            }
+        }
+    }
+
+    _isAddress(content) {
+        content = content.replace('中国', '');
+        const provinceNames = ChinaLocations.getLocationTree()
+            .map(lv1 => lv1.label.replace('特别行政区', '').replace('省', ''));
+        for (let province of provinceNames) {
+            if (content.indexOf(province) >= 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    _parseAddress(content) {
+        content = content.replace('中国', '');
+        const chinaTree = ChinaLocations.getLocationTree();
+        // 省份处理 ---
+        const provinceTailReg = /特别行政区|自治区|省|市$/;
+        for (let province of chinaTree) {
+            const provinceStr = province.label.replace(provinceTailReg, '');
+            // 省份匹配
+            if (content.indexOf(provinceStr) === 0) {
+                // 保存省
+                this.wordData.province = province.label;
+                this.wordData.provinceCode = province.value;
+                // 移除省份
+                const provinceNameReg = new RegExp('^' + provinceStr + '(特别行政区|自治区|省|市)?');
+                content = content.replace(provinceNameReg, '');
+                // 市级处理 ---
+                const cityTailReg = /市|区|县|自治县|自治州|地区$/;
+                for (let city of province.children) {
+                    const cityStr = city.label.replace(cityTailReg, '');
+                    // 市级匹配
+                    if (content.indexOf(cityStr) === 0) {
+                        // 保存市级
+                        this.wordData.city = city.label;
+                        this.wordData.cityCode = city.value;
+                        // 移除市级
+                        const cityNameReg = new RegExp('^' + cityStr + '(市|区|县|自治县|自治州|地区)?');
+                        content = content.replace(cityNameReg, '');
+                        // 区级处理 ---
+                        const distTailReg = /市|区|县|镇|乡|自治县|开发区|新区|矿区|旗|自治旗$/;
+                        for (let dist of city.children) {
+                            const distStr = dist.label.replace(distTailReg, '');
+                            // 区级匹配
+                            if (content.indexOf(distStr) === 0) {
+                                // 保存区级
+                                this.wordData.dist = dist.label;
+                                this.wordData.distCode = dist.value;
+                                // 移除区级
+                                const distNameReg = new RegExp('^' + distStr + '(市|区|县|镇|乡|自治县|开发区|新区|矿区|旗|自治旗)?');
+                                content = content.replace(distNameReg, '');
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        // 省市区都匹配上了,剩下的为街道
+        if (this.wordData.province && this.wordData.city && this.wordData.dist) {
+            this.wordData.street = content;
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/forms/chinaArea/index.js b/forms/chinaArea/index.js
index d673bb1..0d63f1e 100644
--- a/forms/chinaArea/index.js
+++ b/forms/chinaArea/index.js
@@ -5,8 +5,10 @@
 
 import CChinaArea from '@components/forms/chinaArea/CChinaArea.vue';
 import ChinaLocations from '@components/forms/chinaArea/ChinaLocations';
+import { SmartAddress } from '@components/forms/chinaArea/SmartAddress';
 
 export {
     CChinaArea,
     ChinaLocations,
-}
\ No newline at end of file
+    SmartAddress,
+};
\ No newline at end of file

--
Gitblit v1.9.1