Files
thebet365/apps/api/src/domains/identity/sms/phone.util.ts
Mars 312c3c5816 feat(player): 注册账号、登录双模式与移动端性能优化
注册必填 7-32 位账号,手机号区号/本地号分存;登录默认账号模式并支持切换手机号登录;Player i18n 拆包与赛事接口优化。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 10:56:51 +08:00

90 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { appBadRequest } from '../../../shared/common/app-error';
import { isSupportedPhoneDial } from '@thebet365/shared';
/** 归一化为创蓝格式:国家区号 + 本地号码(纯数字,无 + */
export function normalizePhone(countryDial: string, localInput: string): string {
const dial = countryDial.replace(/\D/g, '');
let local = stripLocalPhoneDigits(localInput);
if (!dial || !local) {
throw appBadRequest('PHONE_REQUIRED');
}
if (!isSupportedPhoneDial(dial)) {
throw appBadRequest('PHONE_COUNTRY_UNSUPPORTED');
}
const combined = `${dial}${local}`;
if (combined.length < 10 || combined.length > 15) {
throw appBadRequest('PHONE_INVALID');
}
return combined;
}
/** 提取本地号码(纯数字,去掉前导 0 */
export function stripLocalPhoneDigits(localInput: string): string {
let local = localInput.replace(/\D/g, '');
if (local.startsWith('0') && local.length > 1) {
local = local.replace(/^0+/, '');
}
return local;
}
/** 玩家登录:选国家 + 本地号;字母账号(如 player1原样返回 */
export function resolvePlayerLoginUsername(
input: string,
countryDial?: string,
): string {
const trimmed = input.trim();
if (!trimmed) return trimmed;
if (!/^[\d+\s\-()]+$/.test(trimmed)) {
return trimmed;
}
if (countryDial?.trim()) {
const dial = countryDial.replace(/\D/g, '');
let digits = trimmed.replace(/\D/g, '');
if (digits.startsWith('0') && digits.length > 1) {
digits = digits.replace(/^0+/, '');
}
// 已输入含区号完整号码时,不再重复拼接
if (dial && digits.startsWith(dial) && digits.length >= 10) {
return digits;
}
try {
return normalizePhone(countryDial, trimmed);
} catch {
return trimmed;
}
}
const digits = trimmed.replace(/\D/g, '');
if (digits.length >= 10) return digits;
return trimmed;
}
/** 玩家登录:本地号时在开放国家中生成候选完整号码;字母账号原样返回 */
export function resolvePlayerLoginCandidates(
input: string,
countryDial?: string,
): string[] {
const trimmed = input.trim();
if (!trimmed) return [];
if (!/^[\d+\s\-()]+$/.test(trimmed)) {
return [trimmed];
}
if (countryDial?.trim()) {
return [resolvePlayerLoginUsername(input, countryDial)];
}
const digits = trimmed.replace(/\D/g, '');
if (digits.length >= 10) {
return [digits];
}
return [digits];
}