| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- 'use client';
- import { useState } from 'react';
- import api from '@/lib/api';
- import { useRouter } from 'next/navigation';
- import ForgotPasswordModal from '@/components/ForgotPasswordModal';
- import { useLanguage } from '@/lib/i18n/LanguageContext';
- import { Zap } from 'lucide-react';
- // 1. 引入通用消息弹窗
- import MessageModal from '@/components/common/MessageModal';
- export default function AuthForm() {
- const router = useRouter();
- const { t } = useLanguage();
- const [isLoginMode, setIsLoginMode] = useState<boolean>(true);
- const [loading, setLoading] = useState<boolean>(false);
- const [formData, setFormData] = useState({ email: '', password: '' });
- const [isForgotOpen, setIsForgotOpen] = useState(false);
- // 2. 新增:控制消息弹窗的状态
- const [msgModal, setMsgModal] = useState({
- isOpen: false,
- title: '',
- message: '',
- type: 'info' as 'info' | 'error' | 'success',
- onOk: null as (() => void) | null, // 关闭弹窗后的回调函数
- });
- // 辅助函数:显示消息弹窗
- const showMessage = (message: string, type: 'info' | 'error' | 'success' = 'info', onOk?: () => void) => {
- setMsgModal({
- isOpen: true,
- title: type === 'error' ? t('common.error') : t('common.notice'),
- message,
- type,
- onOk: onOk || null,
- });
- };
- // 处理弹窗关闭
- const handleCloseMsg = () => {
- const callback = msgModal.onOk;
- setMsgModal((prev) => ({ ...prev, isOpen: false }));
- if (callback) callback();
- };
- const handleSubmit = async (e: React.FormEvent) => {
- e.preventDefault();
- setLoading(true);
- try {
- let res;
-
- if (isLoginMode) {
- res = await api.post('/api/auth/login', formData);
- } else {
- res = await api.post('/api/auth/auto-register', {});
- }
-
- const data = res.data.data || res.data;
- const token = data.token || data.access_token;
-
- if (token) {
- localStorage.setItem('rsid', token);
- if (data.user) {
- localStorage.setItem('user_info', JSON.stringify(data.user));
- }
- window.dispatchEvent(new Event('storage'));
-
- if (!isLoginMode) {
- showMessage(t('auth.auto_register_success'), 'success', () => {
- router.push('/dashboard');
- });
- } else {
- router.push('/dashboard');
- }
- } else {
- showMessage(t('auth.login_success_no_token'), 'error');
- }
- } catch (error: any) {
- console.error(error);
- const msg = error.response?.data?.message || t('common.unknown_error');
- showMessage(msg, 'error');
- } finally {
- setLoading(false);
- }
- };
- return (
- <div className="w-full max-w-md p-8 bg-white rounded-xl shadow-xl border border-gray-100">
- <h2 className="text-2xl font-bold text-center mb-6">
- {isLoginMode ? t('auth.welcome_back') : t('auth.auto_register')}
- </h2>
-
- <form onSubmit={handleSubmit} className="space-y-5">
-
- {isLoginMode ? (
- <>
- <div>
- <label className="block text-sm font-medium mb-1 text-gray-700">{t('auth.email_label')}</label>
- <input
- type="email" required
- className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none transition"
- value={formData.email}
- onChange={(e) => setFormData({...formData, email: e.target.value})}
- placeholder={t('auth.email_placeholder')}
- />
- </div>
- <div>
- <div className="flex justify-between items-center mb-1">
- <label className="block text-sm font-medium text-gray-700">{t('auth.password_label')}</label>
- <button
- type="button"
- onClick={() => setIsForgotOpen(true)}
- className="text-xs text-blue-600 hover:text-blue-800 hover:underline"
- >
- {t('auth.forgot_password')}
- </button>
- </div>
- <input
- type="password" required
- className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none transition"
- value={formData.password}
- onChange={(e) => setFormData({...formData, password: e.target.value})}
- placeholder="••••••••"
- />
- </div>
- </>
- ) : (
- <div className="bg-blue-50 p-6 rounded-lg text-center border border-blue-100">
- <div className="flex justify-center mb-3">
- <div className="bg-blue-100 p-3 rounded-full text-blue-600">
- <Zap size={24} />
- </div>
- </div>
- <h3 className="font-bold text-blue-900 mb-2">{t('auth.auto_reg_title')}</h3>
- <p className="text-sm text-blue-700 leading-relaxed">
- {t('auth.auto_reg_desc')}
- </p>
- </div>
- )}
- <button
- type="submit"
- disabled={loading}
- className="w-full py-3 bg-blue-600 text-white rounded-lg font-bold hover:bg-blue-700 transition disabled:opacity-50 shadow-md"
- >
- {loading ? t('common.processing') : (isLoginMode ? t('auth.login_btn') : t('auth.auto_reg_btn_action'))}
- </button>
- </form>
- <div className="mt-6 text-center border-t border-gray-100 pt-4">
- <button
- type="button"
- onClick={() => setIsLoginMode(!isLoginMode)}
- className="text-blue-600 text-sm hover:underline"
- >
- {isLoginMode ? t('auth.no_account') : t('auth.has_account')}
- </button>
- </div>
- <ForgotPasswordModal
- isOpen={isForgotOpen}
- onClose={() => setIsForgotOpen(false)}
- />
- {/* 4. 挂载消息弹窗 */}
- <MessageModal
- isOpen={msgModal.isOpen}
- title={msgModal.title}
- message={msgModal.message}
- type={msgModal.type}
- onClose={handleCloseMsg}
- />
- </div>
- );
- }
|