import React, { useState, useEffect } from 'react' import { APP_VERSION } from '../config/version' import { api } from '../utils/api' import { ErrorCodes } from '../utils/errorCodes' export default function Login() { const [username, setUsername] = useState('') const [password, setPassword] = useState('') const [loading, setLoading] = useState(false) const [error, setError] = useState('') const [captcha, setCaptcha] = useState({ num1: 0, num2: 0, answer: '' }) // 注册相关状态 const [showRegister, setShowRegister] = useState(false) const [registerData, setRegisterData] = useState({ agreeTerms: false, username: '', password: '', confirmPassword: '', email: '', phone: '', verifyCode: '' }) const [registerLoading, setRegisterLoading] = useState(false) const [registerError, setRegisterError] = useState('') // 短信获取相关 const [sendingCode, setSendingCode] = useState(false) const [codeCountdown, setCodeCountdown] = useState(0) const [codeSent, setCodeSent] = useState(false) // 生成获取 useEffect(() => { generateCaptcha() }, []) // 获取倒计时 useEffect(() => { if (codeCountdown > 0) { const timer = setTimeout(() => setCodeCountdown(codeCountdown - 1), 1000) return () => clearTimeout(timer) } }, [codeCountdown]) const generateCaptcha = () => { const num1 = Math.floor(Math.random() * 10) const num2 = Math.floor(Math.random() * 10) setCaptcha({ num1, num2, answer: '' }) } // 发送短信获取 const handleSendCode = async () => { if (!registerData.phone) { setRegisterError('请先输入手机号') return } // 验证手机号格式 const phoneRegex = /^1[3-9]\d{9}$/ if (!phoneRegex.test(registerData.phone)) { setRegisterError('请输入正确的手机号') return } setSendingCode(true) setRegisterError('') try { const res = await fetch('/api/auth/send-verification-code', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone: registerData.phone }) }) const data = await res.json() if (data.success) { setCodeSent(true) setCodeCountdown(60) setRegisterError('') } else { setRegisterError(data.message || '发送失败') } } catch (err) { setRegisterError('发送失败,请稍后重试') } finally { setSendingCode(false) } } // 处理注册 const handleRegister = async () => { // 验证输入 if (!registerData.username || !registerData.password) { setRegisterError('用户名和密码为必填项') return } if (!registerData.agreeTerms) { setRegisterError('请先同意用户协议') return } if (registerData.username.length < 2) { setRegisterError('用户名至少 2 个字符') return } if (registerData.password.length < 8 || !/[A-Z]/.test(registerData.password) || !/[a-z]/.test(registerData.password) || !/[0-9]/.test(registerData.password)) { setRegisterError('密码至少8位,需包含大写、小写、数字') return } if (registerData.password !== registerData.confirmPassword) { setRegisterError('两次输入的密码不一致') return } // 验证手机号 if (!registerData.phone) { setRegisterError('手机号为必填项') return } const phoneRegex = /^1[3-9]\d{9}$/ if (!phoneRegex.test(registerData.phone)) { setRegisterError('请输入正确的手机号') return } // 验证短信获取 if (!registerData.verifyCode) { setRegisterError('请输入短信获取') return } setRegisterLoading(true) setRegisterError('') try { const payload = { username: registerData.username, password: registerData.password, phone: registerData.phone, verifyCode: registerData.verifyCode } if (registerData.email) { payload.email = registerData.email } const res = await fetch('/api/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) const data = await res.json() if (!res.ok) { throw new Error(data.detail || data.error?.message || '注册失败') } alert('注册成功!请登录') setShowRegister(false) setRegisterData({ username: '', password: '', confirmPassword: '', email: '', phone: '', verifyCode: '' }) setCodeSent(false) setCodeCountdown(0) generateCaptcha() } catch (err) { console.error('注册错误:', err) setRegisterError(err.message || '注册失败') } finally { setRegisterLoading(false) } } const handleLogin = async () => { // 验证输入 if (!username || !password) { setError(ErrorCodes.E00020.message) return } if (username.length < 2) { setError(ErrorCodes.E00021.message) return } // 验证获取 const expectedAnswer = captcha.num1 + captcha.num2 if (!captcha.answer || Number(captcha.answer) !== expectedAnswer) { setError(ErrorCodes.E00012.message) return } setLoading(true) setError('') try { console.log('开始登录...') const loginData = await api.auth.login(username, password) console.log('登录响应:', loginData) if (!loginData.access_token) { throw new Error('登录响应中没有 access_token') } localStorage.setItem('token', loginData.access_token) console.log('Token 已保存') const userData = await api.user.me() console.log('用户信息:', userData) localStorage.setItem('user', JSON.stringify(userData)) console.log('用户信息已保存') // 强制刷新页面,确保 React 状态更新 window.location.href = '/' console.log('跳转首页') } catch (err) { console.error('登录错误:', err) const errorCode = err.code || 'E00000' const errorMsg = err.message || '登录失败' setError(`${errorCode}: ${errorMsg}`) } finally { setLoading(false) } } return (
生肖纪念钞管理系统