fix: improve phone number input handling and standardize browser autofill behavior
- Updated `autoComplete` attributes to `tel-national` for better compatibility with domestic phone numbers. - Added `normalizePhoneInput` in `authService` to handle browser autofills with `+86` or `86` prefixes for mainland China numbers. - Enhanced tests to cover phone number normalization logic.
This commit is contained in:
@@ -118,7 +118,7 @@ export function BindPhoneScreen({
|
||||
手机号
|
||||
</PlatformFieldLabel>
|
||||
<PlatformTextField
|
||||
autoComplete="tel"
|
||||
autoComplete="tel-national"
|
||||
inputMode="numeric"
|
||||
value={phone}
|
||||
onChange={(event) => setPhone(event.target.value)}
|
||||
|
||||
@@ -261,7 +261,7 @@ export function LoginScreen({
|
||||
手机号
|
||||
</PlatformFieldLabel>
|
||||
<PlatformTextField
|
||||
autoComplete="tel"
|
||||
autoComplete="tel-national"
|
||||
inputMode="numeric"
|
||||
value={phone}
|
||||
onChange={(event) => setPhone(event.target.value)}
|
||||
@@ -504,7 +504,7 @@ function PhoneCodeForm({
|
||||
手机号
|
||||
</PlatformFieldLabel>
|
||||
<PlatformTextField
|
||||
autoComplete="tel"
|
||||
autoComplete="tel-national"
|
||||
inputMode="numeric"
|
||||
value={phone}
|
||||
onChange={(event) => onPhoneChange(event.target.value)}
|
||||
@@ -600,7 +600,7 @@ function PasswordResetPanel({
|
||||
手机号
|
||||
</PlatformFieldLabel>
|
||||
<PlatformTextField
|
||||
autoComplete="tel"
|
||||
autoComplete="tel-national"
|
||||
inputMode="numeric"
|
||||
value={phone}
|
||||
onChange={(event) => onPhoneChange(event.target.value)}
|
||||
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
liftAuthRiskBlock,
|
||||
loginWithPhoneCode,
|
||||
logoutAllAuthSessions,
|
||||
normalizePhoneInput,
|
||||
redeemRegistrationInviteCode,
|
||||
requestWechatMiniProgramPhoneLogin,
|
||||
revokeAuthSession,
|
||||
@@ -104,6 +105,12 @@ describe('authService', () => {
|
||||
clearStoredAccessToken({ emit: false });
|
||||
});
|
||||
|
||||
it('normalizes mainland China browser autofill phone numbers to national format', () => {
|
||||
expect(normalizePhoneInput('+86 198 7654 3210')).toBe('19876543210');
|
||||
expect(normalizePhoneInput('86-198-7654-3210')).toBe('19876543210');
|
||||
expect(normalizePhoneInput('198 7654 3210')).toBe('19876543210');
|
||||
});
|
||||
|
||||
it('auth entry posts phone password credentials and 写入 access token', async () => {
|
||||
apiClientMocks.requestJson.mockResolvedValue({
|
||||
token: 'jwt-entry-token',
|
||||
@@ -217,7 +224,7 @@ describe('authService', () => {
|
||||
providerRequestId: 'mock-request-id',
|
||||
});
|
||||
|
||||
const result = await sendPhoneLoginCode(' 138 0013 8000 ');
|
||||
const result = await sendPhoneLoginCode('+86 138 0013 8000');
|
||||
|
||||
expect(result.cooldownSeconds).toBe(60);
|
||||
expect(apiClientMocks.requestJson).toHaveBeenCalledWith(
|
||||
@@ -277,7 +284,7 @@ describe('authService', () => {
|
||||
});
|
||||
|
||||
const response = await loginWithPhoneCode(
|
||||
'13800138000',
|
||||
'+86 138 0013 8000',
|
||||
'123456',
|
||||
'spring-2026',
|
||||
);
|
||||
|
||||
@@ -69,7 +69,12 @@ const PUBLIC_AUTH_REQUEST_OPTIONS = {
|
||||
const LAST_LOGIN_PHONE_STORAGE_KEY = 'genarrative:last-login-phone';
|
||||
|
||||
export function normalizePhoneInput(phoneInput: string) {
|
||||
return phoneInput.replace(/[^\d+]/gu, '').trim();
|
||||
const compactPhone = phoneInput.trim().replace(/[^\d+]/gu, '');
|
||||
const mainlandChinaInternationalPhone = compactPhone.match(
|
||||
/^\+?86(1\d{10})$/u,
|
||||
);
|
||||
|
||||
return mainlandChinaInternationalPhone?.[1] ?? compactPhone;
|
||||
}
|
||||
|
||||
export function normalizeInviteCodeInput(inviteCode: string | undefined) {
|
||||
|
||||
Reference in New Issue
Block a user