feat: 修改登录功能以支持手机号登录

This commit is contained in:
zyh 2024-10-22 06:34:56 +00:00
parent 3955a13050
commit 2cd653bbdc
4 changed files with 32 additions and 12 deletions

View File

@ -1,33 +1,40 @@
import React, { useState } from 'react';
import { useNavigate } from '@remix-run/react';
import { useAuth } from '~/hooks/useAuth';
import type { LoginResponse } from '~/routes/api.auth.login';
export function Login() {
const [phone, setPhone] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const [error, setError] = useState<string | null>(null);
const { login } = useAuth();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError(null);
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ phone, password }),
});
if (response.ok) {
const data = (await response.json()) as { token: string };
localStorage.setItem('token', data.token);
navigate('/dashboard');
const data = (await response.json()) as LoginResponse;
if (response.ok && data.token && data.user) {
login(data.token, data.user);
// 登录成功后的处理,例如重定向或显示成功消息
} else {
// 处理错误
setError(data.error || '登录失败,请检查您的手机号和密码');
}
} catch (error) {
console.error('Login failed:', error);
setError('登录失败,请稍后再试');
}
};
return (
<form onSubmit={handleSubmit} className="space-y-6">
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="phone" className="block text-sm font-medium text-bolt-elements-textPrimary">
@ -54,6 +61,7 @@ export function Login() {
className="mt-1 block w-full px-3 py-2 bg-bolt-elements-background-depth-1 border border-bolt-elements-borderColor rounded-md shadow-sm focus:outline-none focus:ring-bolt-elements-button-primary-background focus:border-bolt-elements-button-primary-background"
/>
</div>
{error && <div className="text-red-500 text-sm mt-2">{error}</div>}
<div>
<button
type="submit"

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react';
import { useNavigate } from '@remix-run/react';
interface User {
export interface User {
id: number;
phone: string;
nickname: string;

View File

@ -3,6 +3,18 @@ import type { ActionFunction } from '@remix-run/node';
import { validatePhoneNumber } from '~/utils/validation';
import { verifyLogin, createToken } from '~/utils/auth.server';
export interface LoginResponse {
success: boolean;
token?: string;
user?: {
id: number;
phone: string;
nickname: string;
avatarUrl: string;
};
error?: string;
}
export const action: ActionFunction = async ({ request }) => {
const { phone, password } = await request.json() as { phone: string, password: string };

View File

@ -8,8 +8,8 @@ export async function hashPassword(password: string) {
return bcrypt.hash(password, 10);
}
export async function verifyLogin(email: string, password: string) {
const user = await db('users').where({ email }).first();
export async function verifyLogin(phone: string, password: string) {
const user = await db('users').where({ phone }).first();
if (!user) return null;
const isValid = await bcrypt.compare(password, user.password);