react-native-address-parse 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.OpenHarmony.md +85 -0
- package/README.OpenHarmony_CN.md +97 -0
- package/harmony/AppScope/app.json5 +10 -0
- package/harmony/AppScope/resources/base/element/string.json +8 -0
- package/harmony/AppScope/resources/base/media/app_icon.png +0 -0
- package/harmony/address_parse/BuildProfile.ets +17 -0
- package/harmony/address_parse/Index.ets +2 -0
- package/harmony/address_parse/build-profile.json5 +11 -0
- package/harmony/address_parse/hvigor/hvigor-config.json5 +8 -0
- package/harmony/address_parse/hvigorfile.ts +13 -0
- package/harmony/address_parse/oh-package.json5 +22 -0
- package/harmony/address_parse/src/main/cpp/CMakeLists.txt +8 -0
- package/harmony/address_parse/src/main/cpp/ReactNativeAddressParsePackage.cpp +1 -0
- package/harmony/address_parse/src/main/cpp/ReactNativeAddressParsePackage.h +44 -0
- package/harmony/address_parse/src/main/ets/AddressParsePackage.ets +10 -0
- package/harmony/address_parse/src/main/ets/AddressParseTurboModule.ets +600 -0
- package/harmony/address_parse/src/main/ets/data/Areas.ets +12 -0
- package/harmony/address_parse/src/main/ets/data/Cities.ets +12 -0
- package/harmony/address_parse/src/main/ets/data/GovData.ets +11 -0
- package/harmony/address_parse/src/main/ets/data/Names.ets +6 -0
- package/harmony/address_parse/src/main/ets/data/Provinces.ets +12 -0
- package/harmony/address_parse/src/main/module.json5 +11 -0
- package/harmony/build-profile.json5 +26 -0
- package/harmony/hvigor/hvigor-config.json5 +8 -0
- package/harmony/hvigorfile.ts +6 -0
- package/harmony/oh-package.json5 +6 -0
- package/harmony/react_native_address_parse.har +0 -0
- package/index.d.ts +33 -0
- package/index.tsx +43 -0
- package/package.json +29 -0
- package/src/NativeAddressParse.ts +27 -0
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 react-native-address-parse contributors.
|
|
3
|
+
*
|
|
4
|
+
* Ported from zh-address-parse (https://github.com/zhaocjcc/zh-address-parse, MIT).
|
|
5
|
+
*/
|
|
6
|
+
import { AnyThreadTurboModule, AnyThreadTurboModuleContext } from '@rnoh/react-native-openharmony';
|
|
7
|
+
import { PROVINCES } from './data/Provinces';
|
|
8
|
+
import { CITIES } from './data/Cities';
|
|
9
|
+
import { AREAS } from './data/Areas';
|
|
10
|
+
import { ZH_CN_NAMES } from './data/Names';
|
|
11
|
+
import { GovItem } from './data/GovData';
|
|
12
|
+
|
|
13
|
+
export interface ExtraGovData {
|
|
14
|
+
province?: GovItem[];
|
|
15
|
+
city?: GovItem[];
|
|
16
|
+
area?: GovItem[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ParseOptions {
|
|
20
|
+
type?: number;
|
|
21
|
+
textFilter?: string[];
|
|
22
|
+
nameMaxLength?: number;
|
|
23
|
+
extraGovData?: ExtraGovData;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ParseResult {
|
|
27
|
+
province: string;
|
|
28
|
+
city: string;
|
|
29
|
+
area: string;
|
|
30
|
+
detail: string;
|
|
31
|
+
name: string;
|
|
32
|
+
phone: string;
|
|
33
|
+
postalCode: string;
|
|
34
|
+
provinceCode: string;
|
|
35
|
+
cityCode: string;
|
|
36
|
+
areaCode: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface PhoneResult {
|
|
40
|
+
address: string;
|
|
41
|
+
phone: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface PostalCodeResult {
|
|
45
|
+
address: string;
|
|
46
|
+
postalCode: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface RegionParseResult {
|
|
50
|
+
province: GovItem[];
|
|
51
|
+
city: GovItem[];
|
|
52
|
+
area: GovItem[];
|
|
53
|
+
detail: string[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface ParseState {
|
|
57
|
+
phone: string;
|
|
58
|
+
postalCode: string;
|
|
59
|
+
name: string;
|
|
60
|
+
provinceCode: string;
|
|
61
|
+
cityCode: string;
|
|
62
|
+
areaCode: string;
|
|
63
|
+
province: GovItem[];
|
|
64
|
+
city: GovItem[];
|
|
65
|
+
area: GovItem[];
|
|
66
|
+
detail: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const EMPTY_PROVINCES: GovItem[] = PROVINCES.slice();
|
|
70
|
+
const EMPTY_CITIES: GovItem[] = CITIES.slice();
|
|
71
|
+
const EMPTY_AREAS: GovItem[] = AREAS.slice();
|
|
72
|
+
|
|
73
|
+
let provinces: GovItem[] = EMPTY_PROVINCES.slice();
|
|
74
|
+
let cities: GovItem[] = EMPTY_CITIES.slice();
|
|
75
|
+
let areas: GovItem[] = EMPTY_AREAS.slice();
|
|
76
|
+
|
|
77
|
+
function setExtraGovData(extraGovData?: ExtraGovData): void {
|
|
78
|
+
if (extraGovData !== undefined && extraGovData.province !== undefined && extraGovData.province.length > 0) {
|
|
79
|
+
provinces = provinces.concat(extraGovData.province);
|
|
80
|
+
}
|
|
81
|
+
if (extraGovData !== undefined && extraGovData.city !== undefined && extraGovData.city.length > 0) {
|
|
82
|
+
cities = cities.concat(extraGovData.city);
|
|
83
|
+
}
|
|
84
|
+
if (extraGovData !== undefined && extraGovData.area !== undefined && extraGovData.area.length > 0) {
|
|
85
|
+
areas = areas.concat(extraGovData.area);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function sortAddress(splitAddress: string[]): string[] {
|
|
90
|
+
const result: string[] = [];
|
|
91
|
+
const suffixes: string[] = ['省', '市', '区', '县', '镇'];
|
|
92
|
+
suffixes.forEach((suffix: string) => {
|
|
93
|
+
const index = splitAddress.findIndex((item: string) => item.indexOf(suffix) >= 0);
|
|
94
|
+
if (index >= 0) {
|
|
95
|
+
result.push(splitAddress.splice(index, 1)[0]);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return result.concat(splitAddress);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function emptyRegionResult(): RegionParseResult {
|
|
102
|
+
const r: RegionParseResult = { province: [], city: [], area: [], detail: [] };
|
|
103
|
+
return r;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function parseRegionWithRegexp(fragment: string, hasParseResult: RegionParseResult): RegionParseResult {
|
|
107
|
+
let province = hasParseResult.province;
|
|
108
|
+
let city = hasParseResult.city;
|
|
109
|
+
let area = hasParseResult.area;
|
|
110
|
+
const detail: string[] = [];
|
|
111
|
+
const CH = '[\\u4E00-\\u9FA5]';
|
|
112
|
+
|
|
113
|
+
let matchStr = '';
|
|
114
|
+
if (province.length === 0) {
|
|
115
|
+
for (let i = 1; i < fragment.length; i++) {
|
|
116
|
+
const str = fragment.substring(0, i + 1);
|
|
117
|
+
const regexProvince = new RegExp(`\\{"code":"[0-9]{1,6}","name":"${str}${CH}*?"\\}`, 'g');
|
|
118
|
+
const matchProvince = JSON.stringify(provinces).match(regexProvince);
|
|
119
|
+
if (matchProvince) {
|
|
120
|
+
if (matchProvince.length === 1) {
|
|
121
|
+
province = [];
|
|
122
|
+
matchStr = str;
|
|
123
|
+
province.push(JSON.parse(matchProvince[0]) as GovItem);
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (province.length > 0) {
|
|
130
|
+
fragment = fragment.replace(new RegExp(matchStr, 'g'), '');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (city.length === 0) {
|
|
135
|
+
for (let i = 1; i < fragment.length; i++) {
|
|
136
|
+
const str = fragment.substring(0, i + 1);
|
|
137
|
+
const provinceCode = province.length > 0 ? province[0].code : '[0-9]{1,6}';
|
|
138
|
+
const regexCity = new RegExp(`\\{"code":"[0-9]{1,6}","name":"${str}${CH}*?","provinceCode":"${provinceCode}"\\}`, 'g');
|
|
139
|
+
const matchCity = JSON.stringify(cities).match(regexCity);
|
|
140
|
+
if (matchCity) {
|
|
141
|
+
if (matchCity.length === 1) {
|
|
142
|
+
city = [];
|
|
143
|
+
matchStr = str;
|
|
144
|
+
city.push(JSON.parse(matchCity[0]) as GovItem);
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (city.length > 0) {
|
|
151
|
+
const provinceCode: string = city[0].provinceCode ?? '';
|
|
152
|
+
fragment = fragment.replace(new RegExp(matchStr, 'g'), '');
|
|
153
|
+
if (province.length === 0) {
|
|
154
|
+
const regexProvince = new RegExp(`\\{"code":"${provinceCode}","name":"${CH}+?"\\}`, 'g');
|
|
155
|
+
const matchProvince = JSON.stringify(provinces).match(regexProvince);
|
|
156
|
+
if (matchProvince) {
|
|
157
|
+
province.push(JSON.parse(matchProvince[0]) as GovItem);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (area.length === 0) {
|
|
164
|
+
for (let i = 1; i < fragment.length; i++) {
|
|
165
|
+
const str = fragment.substring(0, i + 1);
|
|
166
|
+
const cityCode = city.length > 0 ? city[0].code : '[0-9]{1,6}';
|
|
167
|
+
const provinceCode = province.length > 0 ? province[0].code : '[0-9]{1,6}';
|
|
168
|
+
const regexArea = new RegExp(`\\{"code":"[0-9]{1,9}","name":"${str}${CH}*?","cityCode":"${cityCode}","provinceCode":"${provinceCode}"\\}`, 'g');
|
|
169
|
+
const matchArea = JSON.stringify(areas).match(regexArea);
|
|
170
|
+
if (matchArea) {
|
|
171
|
+
if (matchArea.length === 1) {
|
|
172
|
+
area = [];
|
|
173
|
+
matchStr = str;
|
|
174
|
+
area.push(JSON.parse(matchArea[0]) as GovItem);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (area.length > 0) {
|
|
181
|
+
const provinceCode: string = area[0].provinceCode ?? '';
|
|
182
|
+
const cityCode: string = area[0].cityCode ?? '';
|
|
183
|
+
fragment = fragment.replace(matchStr, '');
|
|
184
|
+
if (province.length === 0) {
|
|
185
|
+
const regexProvince = new RegExp(`\\{"code":"${provinceCode}","name":"${CH}+?"\\}`, 'g');
|
|
186
|
+
const matchProvince = JSON.stringify(provinces).match(regexProvince);
|
|
187
|
+
if (matchProvince) {
|
|
188
|
+
province.push(JSON.parse(matchProvince[0]) as GovItem);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (city.length === 0) {
|
|
192
|
+
const regexCity = new RegExp(`\\{"code":"${cityCode}","name":"${CH}+?","provinceCode":"${provinceCode}"\\}`, 'g');
|
|
193
|
+
const matchCity = JSON.stringify(cities).match(regexCity);
|
|
194
|
+
if (matchCity) {
|
|
195
|
+
city.push(JSON.parse(matchCity[0]) as GovItem);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (fragment.length > 0) {
|
|
202
|
+
detail.push(fragment);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const result: RegionParseResult = { province, city, area, detail };
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function parseRegion(fragment: string, hasParseResult: RegionParseResult): RegionParseResult {
|
|
210
|
+
const province: GovItem[] = [];
|
|
211
|
+
const city: GovItem[] = [];
|
|
212
|
+
const area: GovItem[] = [];
|
|
213
|
+
const detail: string[] = [];
|
|
214
|
+
|
|
215
|
+
if (hasParseResult.province.length > 0) {
|
|
216
|
+
province.push(...hasParseResult.province);
|
|
217
|
+
} else {
|
|
218
|
+
for (const tempProvince of provinces) {
|
|
219
|
+
const name: string = tempProvince.name;
|
|
220
|
+
let replaceName = '';
|
|
221
|
+
for (let i = name.length; i > 1; i--) {
|
|
222
|
+
const temp = name.substring(0, i);
|
|
223
|
+
if (fragment.indexOf(temp) === 0) {
|
|
224
|
+
replaceName = temp;
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (replaceName) {
|
|
229
|
+
province.push(tempProvince);
|
|
230
|
+
fragment = fragment.replace(new RegExp(replaceName, 'g'), '');
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (hasParseResult.city.length > 0) {
|
|
237
|
+
city.push(...hasParseResult.city);
|
|
238
|
+
} else {
|
|
239
|
+
for (const tempCity of cities) {
|
|
240
|
+
const name: string = tempCity.name;
|
|
241
|
+
const provinceCode: string = tempCity.provinceCode ?? '';
|
|
242
|
+
const currentProvince = province.length > 0 ? province[0] : undefined;
|
|
243
|
+
if (currentProvince) {
|
|
244
|
+
if (currentProvince.code === provinceCode) {
|
|
245
|
+
let replaceName = '';
|
|
246
|
+
for (let i = name.length; i > 1; i--) {
|
|
247
|
+
const temp = name.substring(0, i);
|
|
248
|
+
if (fragment.indexOf(temp) === 0) {
|
|
249
|
+
replaceName = temp;
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (replaceName) {
|
|
254
|
+
city.push(tempCity);
|
|
255
|
+
fragment = fragment.replace(new RegExp(replaceName, 'g'), '');
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
for (let i = name.length; i > 1; i--) {
|
|
261
|
+
const replaceName = name.substring(0, i);
|
|
262
|
+
if (fragment.indexOf(replaceName) === 0) {
|
|
263
|
+
city.push(tempCity);
|
|
264
|
+
const p = provinces.find((item: GovItem) => item.code === provinceCode);
|
|
265
|
+
if (p) {
|
|
266
|
+
province.push(p);
|
|
267
|
+
}
|
|
268
|
+
fragment = fragment.replace(replaceName, '');
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (city.length > 0) {
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
for (const tempArea of areas) {
|
|
280
|
+
const name: string = tempArea.name;
|
|
281
|
+
const provinceCode: string = tempArea.provinceCode ?? '';
|
|
282
|
+
const cityCode: string = tempArea.cityCode ?? '';
|
|
283
|
+
const currentProvince = province.length > 0 ? province[0] : undefined;
|
|
284
|
+
const currentCity = city.length > 0 ? city[0] : undefined;
|
|
285
|
+
|
|
286
|
+
if (currentProvince || currentCity) {
|
|
287
|
+
if ((currentProvince !== undefined && currentProvince.code === provinceCode)
|
|
288
|
+
|| (currentCity !== undefined && currentCity.code === cityCode)) {
|
|
289
|
+
let replaceName = '';
|
|
290
|
+
for (let i = name.length; i > 1; i--) {
|
|
291
|
+
const temp = name.substring(0, i);
|
|
292
|
+
if (fragment.indexOf(temp) === 0) {
|
|
293
|
+
replaceName = temp;
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (replaceName) {
|
|
298
|
+
area.push(tempArea);
|
|
299
|
+
if (!currentCity) {
|
|
300
|
+
const c = cities.find((item: GovItem) => item.code === cityCode);
|
|
301
|
+
if (c) {
|
|
302
|
+
city.push(c);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (!currentProvince) {
|
|
306
|
+
const p = provinces.find((item: GovItem) => item.code === provinceCode);
|
|
307
|
+
if (p) {
|
|
308
|
+
province.push(p);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
fragment = fragment.replace(replaceName, '');
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
for (let i = name.length; i > 1; i--) {
|
|
317
|
+
const replaceName = name.substring(0, i);
|
|
318
|
+
if (fragment.indexOf(replaceName) === 0) {
|
|
319
|
+
area.push(tempArea);
|
|
320
|
+
const c = cities.find((item: GovItem) => item.code === cityCode);
|
|
321
|
+
if (c) {
|
|
322
|
+
city.push(c);
|
|
323
|
+
}
|
|
324
|
+
const p = provinces.find((item: GovItem) => item.code === provinceCode);
|
|
325
|
+
if (p) {
|
|
326
|
+
province.push(p);
|
|
327
|
+
}
|
|
328
|
+
fragment = fragment.replace(replaceName, '');
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (area.length > 0) {
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (fragment.length > 0) {
|
|
339
|
+
detail.push(fragment);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const result: RegionParseResult = { province, city, area, detail };
|
|
343
|
+
return result;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function judgeFragmentIsName(fragment: string, nameMaxLength: number): string {
|
|
347
|
+
if (!fragment || !/[\u4E00-\u9FA5]/.test(fragment)) {
|
|
348
|
+
return '';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const nameCall: string[] = ['先生', '小姐', '同志', '哥哥', '姐姐', '妹妹', '弟弟', '妈妈', '爸爸', '爷爷', '奶奶', '姑姑', '舅舅'];
|
|
352
|
+
const hasCall = nameCall.some((item: string) => fragment.indexOf(item) >= 0);
|
|
353
|
+
if (hasCall) {
|
|
354
|
+
return fragment;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const filters: string[] = ['街道', '乡镇', '镇', '乡'];
|
|
358
|
+
const hasFilter = filters.some((item: string) => fragment.indexOf(item) >= 0);
|
|
359
|
+
if (hasFilter) {
|
|
360
|
+
return '';
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const nameFirst = fragment.substring(0, 1);
|
|
364
|
+
if (fragment.length <= nameMaxLength && fragment.length > 1 && ZH_CN_NAMES.indexOf(nameFirst) >= 0) {
|
|
365
|
+
return fragment;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return '';
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function filterPhone(address: string): PhoneResult {
|
|
372
|
+
let phone = '';
|
|
373
|
+
address = address.replace(/(\d{3})-(\d{4})-(\d{4})/g, '$1$2$3');
|
|
374
|
+
address = address.replace(/(\d{3}) (\d{4}) (\d{4})/g, '$1$2$3');
|
|
375
|
+
address = address.replace(/(\d{4}) (\d{4}) (\d{4})/g, '$1$2$3');
|
|
376
|
+
|
|
377
|
+
const mobileReg = /(0|\+?86-?|17951|)?1[3456789]\d{9}(-\d{4})?/g;
|
|
378
|
+
const mobile = mobileReg.exec(address);
|
|
379
|
+
if (mobile) {
|
|
380
|
+
phone = mobile[0];
|
|
381
|
+
address = address.replace(mobile[0], ' ');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!phone) {
|
|
385
|
+
const landlineReg = /(?:\+?86[- ]?)?(?:\(?0\d{2,3}\)?[- ]?)\d{7,8}(?:-\d{1,6})?/g;
|
|
386
|
+
const landline = landlineReg.exec(address);
|
|
387
|
+
if (landline) {
|
|
388
|
+
phone = landline[0];
|
|
389
|
+
address = address.replace(landline[0], ' ');
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const cleaned = phone.replace(/^\+?86[- ]?/g, '').replace(/[()]/g, '').trim();
|
|
394
|
+
const result: PhoneResult = { address, phone: cleaned };
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function filterPostalCode(address: string): PostalCodeResult {
|
|
399
|
+
let postalCode = '';
|
|
400
|
+
const postalCodeReg = /[1-9]\d{5}(?!\d)/g;
|
|
401
|
+
const code = postalCodeReg.exec(address);
|
|
402
|
+
if (code) {
|
|
403
|
+
postalCode = code[0];
|
|
404
|
+
address = address.replace(code[0], ' ');
|
|
405
|
+
}
|
|
406
|
+
const result: PostalCodeResult = { address, postalCode };
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function cleanAddress(address: string, textFilter: string[]): string {
|
|
411
|
+
address = address
|
|
412
|
+
.replace(/\r\n/g, ' ')
|
|
413
|
+
.replace(/\n/g, ' ')
|
|
414
|
+
.replace(/\t/g, ' ');
|
|
415
|
+
|
|
416
|
+
const search: string[] = [
|
|
417
|
+
'详细地址', '收货地址', '收件地址', '地址', '所在地区', '姓名', '收货人', '收件人',
|
|
418
|
+
'联系人', '收', '邮编', '联系电话', '电话', '联系人手机号码', '手机号码', '手机号',
|
|
419
|
+
'自治区直辖县级行政区划', '省直辖县级行政区划',
|
|
420
|
+
].concat(textFilter);
|
|
421
|
+
search.forEach((str: string) => {
|
|
422
|
+
address = address.replace(new RegExp(str, 'g'), ' ');
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
const pattern = new RegExp("[`~!@$^&*()=|{}':;',\\[\\]\.<>/?~!@¥……&*()——|{}【】‘;:”“’。,、?]", 'g');
|
|
426
|
+
address = address.replace(pattern, ' ');
|
|
427
|
+
|
|
428
|
+
address = address.replace(/ {2,}/g, ' ');
|
|
429
|
+
const municipalities: string[] = ['北京', '上海', '天津', '重庆'];
|
|
430
|
+
municipalities.forEach((str: string) => {
|
|
431
|
+
address = address.replace(str + str, str);
|
|
432
|
+
});
|
|
433
|
+
return address;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export function addressParse(address: string, options: ParseOptions): ParseResult {
|
|
437
|
+
const type = options.type !== undefined ? options.type : 0;
|
|
438
|
+
const textFilter = options.textFilter !== undefined ? options.textFilter : [];
|
|
439
|
+
const nameMaxLength = options.nameMaxLength !== undefined ? options.nameMaxLength : 4;
|
|
440
|
+
const extraGovData = options.extraGovData;
|
|
441
|
+
|
|
442
|
+
const emptyResult: ParseResult = {
|
|
443
|
+
province: '', city: '', area: '', detail: '', name: '',
|
|
444
|
+
phone: '', postalCode: '', provinceCode: '', cityCode: '', areaCode: '',
|
|
445
|
+
};
|
|
446
|
+
if (!address) {
|
|
447
|
+
return emptyResult;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
setExtraGovData(extraGovData);
|
|
451
|
+
|
|
452
|
+
const parseResult: ParseState = {
|
|
453
|
+
phone: '', postalCode: '', name: '',
|
|
454
|
+
provinceCode: '', cityCode: '', areaCode: '',
|
|
455
|
+
province: [], city: [], area: [], detail: [],
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
address = cleanAddress(address, textFilter);
|
|
459
|
+
|
|
460
|
+
const resultPhone = filterPhone(address);
|
|
461
|
+
address = resultPhone.address;
|
|
462
|
+
parseResult.phone = resultPhone.phone;
|
|
463
|
+
|
|
464
|
+
const resultCode = filterPostalCode(address);
|
|
465
|
+
address = resultCode.address;
|
|
466
|
+
parseResult.postalCode = resultCode.postalCode;
|
|
467
|
+
|
|
468
|
+
let splitAddress = address.split(' ').filter((item: string) => item.length > 0 && !/^\d{6,}$/.test(item)).map((item: string) => item.trim());
|
|
469
|
+
splitAddress = sortAddress(splitAddress);
|
|
470
|
+
|
|
471
|
+
splitAddress.forEach((item: string) => {
|
|
472
|
+
if (!parseResult.province[0] || !parseResult.city[0] || !parseResult.area[0]) {
|
|
473
|
+
const seed: RegionParseResult = {
|
|
474
|
+
province: parseResult.province,
|
|
475
|
+
city: parseResult.city,
|
|
476
|
+
area: parseResult.area,
|
|
477
|
+
detail: [],
|
|
478
|
+
};
|
|
479
|
+
let parse: RegionParseResult;
|
|
480
|
+
if (type === 1) {
|
|
481
|
+
parse = parseRegion(item, seed);
|
|
482
|
+
} else {
|
|
483
|
+
parse = parseRegionWithRegexp(item, seed);
|
|
484
|
+
}
|
|
485
|
+
parseResult.province = parse.province;
|
|
486
|
+
parseResult.area = parse.area;
|
|
487
|
+
parseResult.city = parse.city;
|
|
488
|
+
parseResult.detail = parseResult.detail.concat(parse.detail);
|
|
489
|
+
if (parseResult.area[0] !== undefined) {
|
|
490
|
+
parseResult.areaCode = parseResult.area[0].code;
|
|
491
|
+
} else {
|
|
492
|
+
parseResult.areaCode = '';
|
|
493
|
+
}
|
|
494
|
+
if (parseResult.province[0] !== undefined) {
|
|
495
|
+
parseResult.provinceCode = parseResult.province[0].code;
|
|
496
|
+
} else {
|
|
497
|
+
parseResult.provinceCode = '';
|
|
498
|
+
}
|
|
499
|
+
if (parseResult.city[0] !== undefined) {
|
|
500
|
+
parseResult.cityCode = parseResult.city[0].code;
|
|
501
|
+
} else {
|
|
502
|
+
parseResult.cityCode = '';
|
|
503
|
+
}
|
|
504
|
+
} else {
|
|
505
|
+
parseResult.detail.push(item);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
const province = parseResult.province.length > 0 ? parseResult.province[0] : undefined;
|
|
510
|
+
const city = parseResult.city.length > 0 ? parseResult.city[0] : undefined;
|
|
511
|
+
const area = parseResult.area.length > 0 ? parseResult.area[0] : undefined;
|
|
512
|
+
let detail = parseResult.detail;
|
|
513
|
+
|
|
514
|
+
const names: string[] = [];
|
|
515
|
+
if (province !== undefined && province.name) {
|
|
516
|
+
names.push(province.name);
|
|
517
|
+
}
|
|
518
|
+
if (city !== undefined && city.name) {
|
|
519
|
+
names.push(city.name);
|
|
520
|
+
}
|
|
521
|
+
if (area !== undefined && area.name) {
|
|
522
|
+
names.push(area.name);
|
|
523
|
+
}
|
|
524
|
+
if (names.length > 0) {
|
|
525
|
+
detail = detail.map((item: string) => item.replace(new RegExp(names.join('|'), 'g'), ''));
|
|
526
|
+
}
|
|
527
|
+
detail = Array.from(new Set(detail));
|
|
528
|
+
|
|
529
|
+
if (detail.length > 0) {
|
|
530
|
+
const copyDetail: string[] = detail.filter((item: string) => item.length > 0);
|
|
531
|
+
copyDetail.sort((a: string, b: string) => a.length - b.length);
|
|
532
|
+
const index = copyDetail.findIndex((item: string) => judgeFragmentIsName(item, nameMaxLength).length > 0);
|
|
533
|
+
let name = '';
|
|
534
|
+
if (index >= 0) {
|
|
535
|
+
name = copyDetail[index];
|
|
536
|
+
} else if (copyDetail.length > 0 && copyDetail[0].length <= nameMaxLength && /[\u4E00-\u9FA5]/.test(copyDetail[0])) {
|
|
537
|
+
name = copyDetail[0];
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (name.length > 0) {
|
|
541
|
+
parseResult.name = name;
|
|
542
|
+
const idx = detail.findIndex((item: string) => item === name);
|
|
543
|
+
if (idx >= 0) {
|
|
544
|
+
detail.splice(idx, 1);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
let provinceName = '';
|
|
550
|
+
if (province !== undefined) {
|
|
551
|
+
provinceName = province.name;
|
|
552
|
+
}
|
|
553
|
+
let cityName = '';
|
|
554
|
+
if (city !== undefined) {
|
|
555
|
+
cityName = city.name;
|
|
556
|
+
}
|
|
557
|
+
if (cityName === '市辖区' || cityName === '区' || cityName === '县' || cityName === '镇') {
|
|
558
|
+
cityName = provinceName;
|
|
559
|
+
}
|
|
560
|
+
let areaName = '';
|
|
561
|
+
if (area !== undefined) {
|
|
562
|
+
areaName = area.name;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const finalResult: ParseResult = {
|
|
566
|
+
province: provinceName,
|
|
567
|
+
city: cityName,
|
|
568
|
+
area: areaName,
|
|
569
|
+
detail: detail.length > 0 ? detail.join('') : '',
|
|
570
|
+
name: parseResult.name,
|
|
571
|
+
phone: parseResult.phone,
|
|
572
|
+
postalCode: parseResult.postalCode,
|
|
573
|
+
provinceCode: parseResult.provinceCode,
|
|
574
|
+
cityCode: parseResult.cityCode,
|
|
575
|
+
areaCode: parseResult.areaCode,
|
|
576
|
+
};
|
|
577
|
+
return finalResult;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
export class AddressParseTurboModule extends AnyThreadTurboModule {
|
|
581
|
+
public static readonly NAME = 'AddressParse';
|
|
582
|
+
|
|
583
|
+
constructor(ctx: AnyThreadTurboModuleContext) {
|
|
584
|
+
super(ctx);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
parse(
|
|
588
|
+
address: string,
|
|
589
|
+
type: number,
|
|
590
|
+
textFilter: string[],
|
|
591
|
+
nameMaxLength: number,
|
|
592
|
+
extraGovData?: ExtraGovData,
|
|
593
|
+
): ParseResult {
|
|
594
|
+
return addressParse(address, { type, textFilter, nameMaxLength, extraGovData });
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
__onDestroy__(): void {
|
|
598
|
+
super.__onDestroy__();
|
|
599
|
+
}
|
|
600
|
+
}
|