邮件通知设置增加加载/保存状态

This commit is contained in:
mtvpls
2026-01-16 20:55:11 +08:00
parent d7daab795c
commit c8ec2f14b6
+43 -7
View File
@@ -113,6 +113,8 @@ export const UserMenu: React.FC = () => {
// 邮件通知设置 // 邮件通知设置
const [userEmail, setUserEmail] = useState(''); const [userEmail, setUserEmail] = useState('');
const [emailNotifications, setEmailNotifications] = useState(false); const [emailNotifications, setEmailNotifications] = useState(false);
const [emailSettingsLoading, setEmailSettingsLoading] = useState(false);
const [emailSettingsSaving, setEmailSettingsSaving] = useState(false);
// 折叠面板状态 // 折叠面板状态
const [isDoubanSectionOpen, setIsDoubanSectionOpen] = useState(true); const [isDoubanSectionOpen, setIsDoubanSectionOpen] = useState(true);
@@ -396,14 +398,12 @@ export const UserMenu: React.FC = () => {
if (savedSearchTraditionalToSimplified !== null) { if (savedSearchTraditionalToSimplified !== null) {
setSearchTraditionalToSimplified(savedSearchTraditionalToSimplified === 'true'); setSearchTraditionalToSimplified(savedSearchTraditionalToSimplified === 'true');
} }
// 加载邮件通知设置
loadEmailSettings();
} }
}, []); }, []);
// 加载邮件通知设置 // 加载邮件通知设置
const loadEmailSettings = async () => { const loadEmailSettings = async () => {
setEmailSettingsLoading(true);
try { try {
const response = await fetch('/api/user/email-settings'); const response = await fetch('/api/user/email-settings');
if (response.ok) { if (response.ok) {
@@ -413,11 +413,14 @@ export const UserMenu: React.FC = () => {
} }
} catch (error) { } catch (error) {
console.error('加载邮件设置失败:', error); console.error('加载邮件设置失败:', error);
} finally {
setEmailSettingsLoading(false);
} }
}; };
// 保存邮件通知设置 // 保存邮件通知设置
const handleSaveEmailSettings = async () => { const handleSaveEmailSettings = async () => {
setEmailSettingsSaving(true);
try { try {
const response = await fetch('/api/user/email-settings', { const response = await fetch('/api/user/email-settings', {
method: 'POST', method: 'POST',
@@ -454,6 +457,8 @@ export const UserMenu: React.FC = () => {
messageEl.className = 'text-xs text-center text-red-600 dark:text-red-400'; messageEl.className = 'text-xs text-center text-red-600 dark:text-red-400';
messageEl.classList.remove('hidden'); messageEl.classList.remove('hidden');
} }
} finally {
setEmailSettingsSaving(false);
} }
}; };
@@ -921,6 +926,8 @@ export const UserMenu: React.FC = () => {
e.stopPropagation(); e.stopPropagation();
setIsOpen(false); setIsOpen(false);
setIsEmailSettingsOpen(true); setIsEmailSettingsOpen(true);
// 懒加载:打开面板时才请求邮件设置
loadEmailSettings();
}} }}
className='p-0.5 rounded hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors' className='p-0.5 rounded hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors'
title='邮件通知设置' title='邮件通知设置'
@@ -2132,6 +2139,24 @@ export const UserMenu: React.FC = () => {
</div> </div>
{/* 表单 */} {/* 表单 */}
{emailSettingsLoading ? (
<div className='space-y-4'>
{/* 加载骨架屏 */}
<div className='animate-pulse'>
<div className='h-4 bg-gray-200 dark:bg-gray-700 rounded w-20 mb-2'></div>
<div className='h-10 bg-gray-200 dark:bg-gray-700 rounded'></div>
</div>
<div className='animate-pulse'>
<div className='h-20 bg-gray-200 dark:bg-gray-700 rounded'></div>
</div>
<div className='animate-pulse'>
<div className='h-10 bg-gray-200 dark:bg-gray-700 rounded'></div>
</div>
<div className='text-center text-sm text-gray-500 dark:text-gray-400'>
...
</div>
</div>
) : (
<div className='space-y-4'> <div className='space-y-4'>
<div> <div>
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'> <label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
@@ -2142,7 +2167,8 @@ export const UserMenu: React.FC = () => {
value={userEmail} value={userEmail}
onChange={(e) => setUserEmail(e.target.value)} onChange={(e) => setUserEmail(e.target.value)}
placeholder='输入您的邮箱地址' placeholder='输入您的邮箱地址'
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500' disabled={emailSettingsSaving}
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed'
/> />
</div> </div>
@@ -2157,7 +2183,8 @@ export const UserMenu: React.FC = () => {
</div> </div>
<button <button
onClick={() => setEmailNotifications(!emailNotifications)} onClick={() => setEmailNotifications(!emailNotifications)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${ disabled={emailSettingsSaving}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${
emailNotifications ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700' emailNotifications ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700'
}`} }`}
> >
@@ -2171,13 +2198,22 @@ export const UserMenu: React.FC = () => {
<button <button
onClick={handleSaveEmailSettings} onClick={handleSaveEmailSettings}
className='w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition-colors' disabled={emailSettingsSaving}
className='w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 dark:disabled:bg-blue-500 text-white text-sm font-medium rounded-lg transition-colors disabled:cursor-not-allowed flex items-center justify-center gap-2'
> >
{emailSettingsSaving ? (
<>
<div className='w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin'></div>
<span>...</span>
</>
) : (
'保存设置'
)}
</button> </button>
<p id='email-settings-message' className='text-xs text-center hidden'></p> <p id='email-settings-message' className='text-xs text-center hidden'></p>
</div> </div>
)}
{/* 提示信息 */} {/* 提示信息 */}
<div className='mt-6 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg'> <div className='mt-6 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg'>