'use client'; import { useState, useEffect } from 'react'; import api from '@/lib/api'; import { X, Mail, Loader2, Save, Lock, ArrowRight, ArrowLeft } from 'lucide-react'; import { useLanguage } from '@/lib/i18n/LanguageContext'; // 1. 引入通用消息弹窗 import MessageModal from '@/components/common/MessageModal'; interface BindEmailModalProps { isOpen: boolean; onClose: () => void; onSuccess: () => void; } export default function BindEmailModal({ isOpen, onClose, onSuccess }: BindEmailModalProps) { const { t } = useLanguage(); const [step, setStep] = useState<1 | 2>(1); const [loading, setLoading] = useState(false); const [email, setEmail] = useState(''); const [code, setCode] = useState(''); const [countdown, setCountdown] = useState(0); // 2. 消息弹窗状态 const [msgModal, setMsgModal] = useState({ isOpen: false, title: '', message: '', type: 'info' as 'info' | 'error' | 'success', onOk: null as (() => void) | null, }); const showMessage = (msg: string, type: 'info' | 'error' | 'success' = 'info', onOk?: () => void) => { setMsgModal({ isOpen: true, title: type === 'error' ? t('common.error') : t('common.notice'), message: msg, type, onOk: onOk || null, }); }; const handleCloseMsg = () => { const callback = msgModal.onOk; setMsgModal(prev => ({ ...prev, isOpen: false })); if (callback) callback(); }; useEffect(() => { let timer: NodeJS.Timeout; if (countdown > 0) { timer = setTimeout(() => setCountdown(c => c - 1), 1000); } return () => clearTimeout(timer); }, [countdown]); useEffect(() => { if (isOpen) { setStep(1); setCode(''); } }, [isOpen]); const handleSendCode = async (e?: React.FormEvent) => { if (e) e.preventDefault(); if (!email) return showMessage(t('bind_email.alert_input_email'), 'error'); if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return showMessage(t('bind_email.alert_invalid_email'), 'error'); setLoading(true); try { await api.post('/api/auth/send-bind-code', { email }); showMessage(`${t('bind_email.alert_code_sent')} ${email}`, 'success'); setStep(2); setCountdown(60); } catch (error: any) { console.error(error); const msg = error.response?.data?.message || t('common.unknown_error'); showMessage(`${t('bind_email.alert_send_failed')}: ${msg}`, 'error'); } finally { setLoading(false); } }; const handleVerifyAndBind = async (e: React.FormEvent) => { e.preventDefault(); if (!code) return showMessage(t('bind_email.alert_input_code'), 'error'); if (code.length !== 6) return showMessage(t('bind_email.alert_code_length'), 'error'); setLoading(true); try { const res = await api.post('/api/auth/bind-email', { email, code }); const data = res.data.data || res.data; const newToken = data.token || data.access_token; const newUser = data.user; if (newToken) { localStorage.setItem('rsid', newToken); if (newUser) { localStorage.setItem('user_info', JSON.stringify(newUser)); } else { const oldUser = JSON.parse(localStorage.getItem('user_info') || '{}'); localStorage.setItem('user_info', JSON.stringify({ ...oldUser, email })); } window.dispatchEvent(new Event('storage')); // 绑定成功后提示,点击确认后关闭弹窗并执行 onSuccess showMessage(t('bind_email.success'), 'success', () => { onSuccess(); onClose(); }); } else { throw new Error("Token missing"); } } catch (error: any) { console.error(error); const msg = error.response?.data?.message || t('common.unknown_error'); showMessage(`${t('bind_email.failed')}: ${msg}`, 'error'); } finally { setLoading(false); } }; if (!isOpen) return null; return (
{/* Header */}

{step === 1 ? : } {step === 1 ? t('bind_email.title_step1') : t('bind_email.title_step2')}

{/* Progress Indicator */}
= 1 ? 'bg-blue-600' : 'bg-gray-200'}`}>
= 2 ? 'bg-blue-600' : 'bg-gray-200'}`}>
{step === 1 ? (

{t('bind_email.desc_step1')}

setEmail(e.target.value)} />
) : (

{t('bind_email.desc_step2_prefix')} {email}{t('bind_email.desc_step2_suffix')}

setCode(e.target.value)} />
)}
{/* 3. 挂载消息弹窗 */}
); }