feat(player): 注册账号、登录双模式与移动端性能优化

注册必填 7-32 位账号,手机号区号/本地号分存;登录默认账号模式并支持切换手机号登录;Player i18n 拆包与赛事接口优化。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-12 10:56:51 +08:00
parent 83f0f380c5
commit 312c3c5816
35 changed files with 1944 additions and 1394 deletions

View File

@@ -4,7 +4,7 @@ import { isSupportedPhoneDial } from '@thebet365/shared';
/** 归一化为创蓝格式:国家区号 + 本地号码(纯数字,无 + */
export function normalizePhone(countryDial: string, localInput: string): string {
const dial = countryDial.replace(/\D/g, '');
let local = localInput.replace(/\D/g, '');
let local = stripLocalPhoneDigits(localInput);
if (!dial || !local) {
throw appBadRequest('PHONE_REQUIRED');
@@ -13,11 +13,6 @@ export function normalizePhone(countryDial: string, localInput: string): string
throw appBadRequest('PHONE_COUNTRY_UNSUPPORTED');
}
// 马来西亚等本地号常以 0 开头
if (local.startsWith('0') && local.length > 1) {
local = local.replace(/^0+/, '');
}
const combined = `${dial}${local}`;
if (combined.length < 10 || combined.length > 15) {
throw appBadRequest('PHONE_INVALID');
@@ -25,6 +20,15 @@ export function normalizePhone(countryDial: string, localInput: string): string
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,
@@ -38,6 +42,15 @@ export function resolvePlayerLoginUsername(
}
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 {
@@ -50,3 +63,27 @@ export function resolvePlayerLoginUsername(
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];
}