import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; export default function Profile() { const { user } = useAuth(); const navigate = useNavigate(); const [newEmail, setNewEmail] = useState(''); const [newPassword, setNewPassword] = useState(''); const [emailCode, setEmailCode] = useState(''); const [loadingCode, setLoadingCode] = useState(false); const [loadingSubmit, setLoadingSubmit] = useState(false); const [message, setMessage] = useState(''); const [error, setError] = useState(''); const [smtpEnabled, setSmtpEnabled] = useState(false); useEffect(() => { fetch('/api/sys/config') .then(res => res.json()) .then(data => { if (data && data.smtp_enabled !== undefined) { setSmtpEnabled(data.smtp_enabled); } }) .catch(err => console.error("获取系统配置失败:", err)); }, []); if (!user) { navigate('/login'); return null; } const handleSendCode = async () => { setError(''); setMessage(''); setLoadingCode(true); try { const token = localStorage.getItem('token'); const res = await fetch('/api/auth/send-code', { method: 'POST', headers: { Authorization: `Bearer ${token}` } }); const data = await res.json(); if (!res.ok) throw new Error(data.detail || data.error); setMessage(data.message || '验证码已发送到原邮箱 (请查看后端控制台输出模拟邮件)'); } catch (err) { setError(err.message); } finally { setLoadingCode(false); } }; const handleSubmit = async (e) => { e.preventDefault(); setError(''); setMessage(''); if (!newEmail && !newPassword) { setError('请输入你要修改的新邮箱或新密码'); return; } if (smtpEnabled && !emailCode) { setError('请输入原邮箱收到的验证码'); return; } setLoadingSubmit(true); try { const token = localStorage.getItem('token'); const res = await fetch('/api/auth/update-profile', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, body: JSON.stringify({ email_code: emailCode || null, new_email: newEmail || null, new_password: newPassword || null }) }); const data = await res.json(); if (!res.ok) throw new Error(data.detail || data.error); setMessage('信息更新成功!如果您修改了密码,建议重新登录。'); setNewEmail(''); setNewPassword(''); setEmailCode(''); } catch (err) { setError(err.message); } finally { setLoadingSubmit(false); } }; return (

修改个人信息

{error &&
{error}
} {message &&
{message}
}

当前账号: {user.username}

当前邮箱: {user.email || '未绑定'}

setNewEmail(e.target.value)} style={styles.input} />
setNewPassword(e.target.value)} style={styles.input} minLength={6} />

{smtpEnabled && (
setEmailCode(e.target.value)} style={{...styles.input, flex: 1}} placeholder="请输入6位验证码" maxLength={6} />
我们向您的原邮箱发送了一封包含验证码的邮件,请查收以验证您的身份。
)}
); } const styles = { container: { display: 'flex', justifyContent: 'center', padding: '40px 20px', minHeight: 'calc(100vh - 60px)' }, card: { width: '100%', maxWidth: '450px', background: 'white', borderRadius: '8px', padding: '30px', boxShadow: '0 2px 10px rgba(0,0,0,0.05)' }, title: { margin: '0 0 20px 0', fontSize: '20px', color: '#111827' }, infoBox: { backgroundColor: '#f9fafb', padding: '15px', borderRadius: '6px', marginBottom: '20px', fontSize: '14px', color: '#4b5563', border: '1px solid #e5e7eb' }, formGroup: { marginBottom: '16px' }, label: { display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: '500', color: '#374151' }, input: { width: '100%', padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px', boxSizing: 'border-box' }, flexRow: { display: 'flex', gap: '10px' }, btnSecondary: { padding: '0 15px', backgroundColor: '#f3f4f6', border: '1px solid #d1d5db', borderRadius: '6px', cursor: 'pointer', fontSize: '13px', color: '#374151', whiteSpace: 'nowrap' }, button: { width: '100%', padding: '12px', backgroundColor: '#3b82f6', color: 'white', border: 'none', borderRadius: '6px', fontSize: '15px', cursor: 'pointer', marginTop: '10px', fontWeight: '500' }, error: { color: '#ef4444', backgroundColor: '#fef2f2', padding: '10px', borderRadius: '6px', marginBottom: '16px', fontSize: '13px' }, success: { color: '#10b981', backgroundColor: '#ecfdf5', padding: '10px', borderRadius: '6px', marginBottom: '16px', fontSize: '13px' }, divider: { border: 'none', borderTop: '1px solid #e5e7eb', margin: '20px 0' }, hintText: { fontSize: '12px', color: '#9ca3af', display: 'block', marginTop: '6px' } };