Files
happy-life-star/life-script/src/pages/LoginPage.jsx
T
2025-12-22 16:38:06 +08:00

146 lines
4.1 KiB
React
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 { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { GlassCard, GlassInput, GlassButton } from '../components/ui';
import useStore from '../store/useStore';
import useCountdown from '../hooks/useCountdown';
/**
* LoginPage 组件
* 登录页面,包含手机号和验证码输入
*/
const LoginPage = () => {
const navigate = useNavigate();
const { login, getSmsCode, setLogin, loading } = useStore();
// 表单状态
const [phone, setPhone] = useState('');
const [code, setCode] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
// 倒计时
const { countdown, isActive, start } = useCountdown(60);
/**
* 处理获取验证码
*/
const handleGetCode = async () => {
if (phone.length !== 11) {
alert('请输入正确的手机号');
return;
}
try {
start();
// 调用后端获取验证码
await getSmsCode(phone);
alert('验证码已发送');
} catch (error) {
// 后端不可用时,使用模拟验证码
alert('验证码已发送 (模拟验证码: 888888)');
}
};
/**
* 处理登录提交
*/
const handleSubmit = async () => {
if (phone.length !== 11) {
alert('请输入正确的手机号');
return;
}
if (code.length !== 6) {
alert('请输入6位验证码');
return;
}
setIsSubmitting(true);
try {
// 尝试调用后端登录
await login(phone, code);
navigate('/onboarding');
} catch (error) {
// 后端不可用时,使用本地验证
if (code === '888888') {
setLogin(true, phone);
navigate('/onboarding');
} else {
alert('验证失败,请检查手机号或验证码');
}
} finally {
setIsSubmitting(false);
}
};
return (
<div className="w-full h-full flex items-center justify-center p-6 animate-fade-in">
<GlassCard className="max-w-md w-full space-y-8 border-white/5 shadow-2xl" padding="lg">
{/* 标题区域 */}
<div className="text-center space-y-2">
<h2 className="text-3xl font-serif tracking-wider text-white/90">
欢迎回来
</h2>
<p className="text-sm text-white/40 italic">
开启你的数字生命档案
</p>
</div>
{/* 表单区域 */}
<div className="space-y-4">
{/* 手机号输入 */}
<GlassInput
label="手机号码"
type="tel"
placeholder="输入手机号"
value={phone}
onChange={setPhone}
maxLength={11}
className="text-center tracking-[0.1em]"
/>
{/* 验证码输入 */}
<div className="grid grid-cols-3 gap-3">
<div className="col-span-2">
<GlassInput
label="验证码"
type="text"
placeholder="六位验证码"
value={code}
onChange={setCode}
maxLength={6}
className="text-center"
/>
</div>
<div className="flex items-end">
<button
onClick={handleGetCode}
disabled={isActive || loading}
className="w-full h-[46px] rounded-2xl border border-white/5 bg-white/5 text-[10px] uppercase tracking-tighter hover:bg-white/10 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
>
{isActive ? `${countdown}S` : '获取'}
</button>
</div>
</div>
</div>
{/* 登录按钮 */}
<GlassButton
variant="primary"
onClick={handleSubmit}
loading={isSubmitting || loading}
className="w-full"
>
开启旅程
</GlassButton>
{/* 协议文字 */}
<p className="text-[10px] text-center text-white/20 px-4 leading-relaxed">
登录即代表同意用户协议隐私政策我们将妥善保管您的生命数据
</p>
</GlassCard>
</div>
);
};
export default LoginPage;