Skip to content

Commit 193f6a4

Browse files
committed
fix: 更新手机号绑定功能,支持国际号码格式及验证
1 parent a5779a7 commit 193f6a4

3 files changed

Lines changed: 527 additions & 108 deletions

File tree

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@
3131
"dependencies": {
3232
"@element-plus/icons-vue": "^2.3.2",
3333
"@imengyu/vue3-context-menu": "^1.5.4",
34-
"@jx3box/jx3box-common": "^9.2.3",
34+
"@jx3box/jx3box-common": "^9.2.4",
3535
"@jx3box/jx3box-data": "^3.9.5",
36-
"@jx3box/jx3box-editor": "^3.1.4",
36+
"@jx3box/jx3box-editor": "^3.1.5",
3737
"@jx3box/jx3box-emotion": "^1.3.0",
3838
"@jx3box/jx3box-facedat": "^2.6.4",
3939
"@jx3box/jx3box-macro": "^1.0.3",
4040
"@jx3box/jx3box-talent": "^1.3.13",
41-
"@jx3box/jx3box-ui": "^2.1.18",
41+
"@jx3box/jx3box-ui": "^2.2.2",
4242
"@microsoft/signalr": "^8.0.0",
4343
"@tinymce/tinymce-vue": "^5.1.1",
4444
"@vueuse/core": "^9.13.0",
@@ -55,6 +55,7 @@
5555
"js-base64": "^3.7.5",
5656
"jsencrypt": "^3.3.2",
5757
"katex": "^0.16.9",
58+
"libphonenumber-js": "^1.12.42",
5859
"localforage": "^1.7.3",
5960
"lodash": "^4.17.21",
6061
"lua-json": "^1.0.0",

src/assets/js/phone.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { getCountries, getCountryCallingCode, parsePhoneNumberFromString } from "libphonenumber-js";
2+
3+
const regionNames =
4+
typeof Intl !== "undefined" && typeof Intl.DisplayNames === "function"
5+
? new Intl.DisplayNames(["zh-CN"], { type: "region" })
6+
: null;
7+
8+
function maskSegment(value) {
9+
const text = String(value || "").trim();
10+
if (!text) {
11+
return "";
12+
}
13+
if (text.length <= 4) {
14+
return text;
15+
}
16+
if (text.length <= 6) {
17+
return `${text.slice(0, 2)}***${text.slice(-2)}`;
18+
}
19+
if (text.length <= 8) {
20+
return `${text.slice(0, 3)}***${text.slice(-2)}`;
21+
}
22+
return `${text.slice(0, 3)}****${text.slice(-4)}`;
23+
}
24+
25+
export const PHONE_COUNTRY_OPTIONS = getCountries()
26+
.map((iso2) => ({
27+
iso2,
28+
name: regionNames?.of(iso2) || iso2,
29+
callingCode: getCountryCallingCode(iso2),
30+
}))
31+
.sort((a, b) => {
32+
if (a.iso2 === "CN") return -1;
33+
if (b.iso2 === "CN") return 1;
34+
return a.name.localeCompare(b.name, "zh-CN");
35+
});
36+
37+
export function normalizeBindPhone(phone, country = "CN") {
38+
const value = String(phone || "").trim();
39+
if (!value) {
40+
return "";
41+
}
42+
43+
const phoneNumber = value.startsWith("+")
44+
? parsePhoneNumberFromString(value)
45+
: parsePhoneNumberFromString(value, country || "CN");
46+
47+
return phoneNumber?.isValid() ? phoneNumber.number : "";
48+
}
49+
50+
export function normalizeStoredPhone(phone) {
51+
const value = String(phone || "").trim();
52+
if (!value) {
53+
return "";
54+
}
55+
56+
return normalizeBindPhone(value, value.startsWith("+") ? undefined : "CN");
57+
}
58+
59+
export function detectPhoneCountry(phone) {
60+
const normalized = normalizeStoredPhone(phone);
61+
if (!normalized) {
62+
return "CN";
63+
}
64+
65+
return parsePhoneNumberFromString(normalized)?.country || "CN";
66+
}
67+
68+
export function maskPhone(phone) {
69+
const value = String(phone || "").trim();
70+
if (!value) {
71+
return "";
72+
}
73+
74+
const normalized = normalizeStoredPhone(value);
75+
const phoneNumber = normalized ? parsePhoneNumberFromString(normalized) : null;
76+
if (phoneNumber?.isValid()) {
77+
const prefix = `+${phoneNumber.countryCallingCode}`;
78+
const national = maskSegment(phoneNumber.nationalNumber);
79+
return national ? `${prefix} ${national}` : prefix;
80+
}
81+
82+
const digits = value.replace(/\D/g, "");
83+
if (digits.length >= 7) {
84+
return maskSegment(digits);
85+
}
86+
87+
return value;
88+
}

0 commit comments

Comments
 (0)