// Supabase configuration - 使用从页面传递的全局变量或默认值 const SUPABASE_URL = window.SUPABASE_URL || 'https://smbksxmlfxfiohahdeqv.supabase.co'; const SUPABASE_ANON_KEY = window.SUPABASE_ANON_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InNtYmtzeG1sZnhmaW9oYWhkZXF2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDQzODA3MjQsImV4cCI6MjA1OTk1NjcyNH0.9bpNQPeMdzvlnUT0yvWscr4rwfbWxOiHa4tUNhDQhVQ'; // 创建一个全局supabase客户端变量 window.supabaseClient = null; // 增强的Supabase初始化函数 function initializeSupabase() { console.log('尝试初始化Supabase客户端...'); console.log('Supabase URL:', SUPABASE_URL); console.log('Supabase脚本已加载:', typeof supabase !== 'undefined'); // 检查supabase库是否可用 if (typeof supabase !== 'undefined') { try { // 创建Supabase客户端实例 window.supabaseClient = supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY, { auth: { persistSession: true, storage: window.localStorage, autoRefreshToken: true, detectSessionInUrl: true } }); console.log('Supabase客户端初始化成功!'); return window.supabaseClient; } catch (error) { console.error('初始化Supabase客户端时出错:', error); showAlert('认证服务初始化失败,请刷新页面重试', 'warning'); return null; } } else { console.error('Supabase JS库未加载'); // 显示加载错误 showAlert('正在加载必要组件,请稍候...', 'info'); // 设置重试 setTimeout(() => { // 100ms后再次尝试 if (typeof supabase !== 'undefined') { window.supabaseClient = initializeSupabase(); showAlert('认证服务已就绪', 'success'); } else { console.error('Supabase JS库加载失败,可能影响登录功能'); showAlert('认证服务加载失败,请刷新页面', 'danger'); } }, 1000); // 增加延迟时间以给CDN加载更多时间 return null; } } // 初始化认证系统 document.addEventListener('DOMContentLoaded', function() { console.log('DOM加载完成,初始化认证系统...'); window.supabaseClient = initializeSupabase(); // 添加页面可见性变化监听 document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'visible') { console.log('页面重新可见,检查认证状态...'); // 页面重新可见时检查客户端状态 if (!window.supabaseClient) { console.log('Supabase客户端不存在,重新初始化'); window.supabaseClient = initializeSupabase(); } // 检查用户会话 checkUser(); } }); }); // DOM elements const authButtons = document.getElementById('auth-buttons'); const userProfile = document.getElementById('user-profile'); const usernameElement = document.getElementById('username'); const loginButton = document.getElementById('login-button'); const signupButton = document.getElementById('signup-button'); const logoutButton = document.getElementById('logout-button'); const authModal = new bootstrap.Modal(document.getElementById('authModal')); const authModalLabel = document.getElementById('authModalLabel'); // Form elements const loginForm = document.getElementById('login-form'); const signupForm = document.getElementById('signup-form'); const resetForm = document.getElementById('reset-form'); const switchToSignup = document.getElementById('switch-to-signup'); const switchToLogin = document.getElementById('switch-to-login'); const forgotPassword = document.getElementById('forgot-password'); const backToLogin = document.getElementById('back-to-login'); const loginFooter = document.getElementById('login-footer'); const signupFooter = document.getElementById('signup-footer'); const resetFooter = document.getElementById('reset-footer'); // 增强的用户会话检查函数 async function checkUser() { try { console.log('检查用户登录状态...'); if (!window.supabaseClient) { console.error('Supabase客户端未初始化,正在尝试重新初始化'); window.supabaseClient = initializeSupabase(); // 如果仍然未初始化,则返回null if (!window.supabaseClient) { console.error('无法初始化Supabase客户端,登录功能可能不可用'); showAlert('认证服务暂时不可用,请稍后再试', 'warning'); return null; } } console.log('调用Supabase获取用户信息...'); const { data: { user }, error } = await window.supabaseClient.auth.getUser(); if (error) { console.error('获取用户信息时出错:', error.message); throw error; } if (user) { console.log('已找到登录用户:', user.email); updateUserInterface(user); return user; } console.log('未找到登录用户'); return null; } catch (error) { console.error('检查用户会话时出错:', error.message); // 不显示错误通知,因为这是后台检查 return null; } } // Update UI based on authentication state function updateUserInterface(user) { if (user) { // User is logged in authButtons.classList.add('d-none'); userProfile.classList.remove('d-none'); usernameElement.textContent = user.email.split('@')[0]; } else { // User is logged out authButtons.classList.remove('d-none'); userProfile.classList.add('d-none'); } } // Show login form function showLoginForm() { authModalLabel.textContent = '登录'; loginForm.classList.remove('d-none'); signupForm.classList.add('d-none'); resetForm.classList.add('d-none'); loginFooter.classList.remove('d-none'); signupFooter.classList.add('d-none'); resetFooter.classList.add('d-none'); } // Show signup form function showSignupForm() { authModalLabel.textContent = '注册'; loginForm.classList.add('d-none'); signupForm.classList.remove('d-none'); resetForm.classList.add('d-none'); loginFooter.classList.add('d-none'); signupFooter.classList.remove('d-none'); resetFooter.classList.add('d-none'); } // Show password reset form function showResetForm() { authModalLabel.textContent = '重置密码'; loginForm.classList.add('d-none'); signupForm.classList.add('d-none'); resetForm.classList.remove('d-none'); loginFooter.classList.add('d-none'); signupFooter.classList.add('d-none'); resetFooter.classList.remove('d-none'); } // 增强的用户登录函数 async function loginUser(email, password) { let submitBtn = null; try { // 先检查Supabase客户端 if (!window.supabaseClient) { console.log('登录前初始化Supabase客户端'); window.supabaseClient = initializeSupabase(); // 如果仍然未初始化,则抛出错误 if (!window.supabaseClient) { throw new Error('认证系统未就绪,请刷新页面重试'); } } // 显示加载状态 submitBtn = document.querySelector('#login-form button[type="submit"]'); const originalText = submitBtn ? submitBtn.innerHTML : '登录'; if (submitBtn) { submitBtn.disabled = true; submitBtn.innerHTML = ' 登录中...'; } console.log('尝试登录用户:', email); // 调用Supabase登录API const { data, error } = await window.supabaseClient.auth.signInWithPassword({ email: email, password: password }); if (error) { console.error('登录失败:', error.message); throw error; } console.log('登录成功:', data.user.email); // 在localStorage中存储用户数据以提高持久性 localStorage.setItem('userEmail', data.user.email); updateUserInterface(data.user); authModal.hide(); showAlert('登录成功!', 'success'); // Redirect to dashboard if on homepage if (window.location.pathname.includes('index.html') || window.location.pathname === '/') { setTimeout(() => { window.location.href = 'dashboard.html'; }, 1000); } return data.user; } catch (error) { console.error('Error logging in:', error.message); let errorMessage = '登录失败'; // Provide user-friendly error messages if (error.message.includes('Invalid login credentials')) { errorMessage = '邮箱或密码不正确,请重试'; } else if (error.message.includes('Email not confirmed')) { errorMessage = '请先验证您的邮箱后再登录'; } else { errorMessage = `登录失败: ${error.message}`; } showAlert(errorMessage, 'danger'); return null; } finally { // Reset button state const submitBtn = document.querySelector('#login-form button[type="submit"]'); if (submitBtn) { submitBtn.disabled = false; submitBtn.innerHTML = '登录'; } } } // Register user async function registerUser(email, password) { try { // Show loading state const submitBtn = document.querySelector('#signup-form button[type="submit"]'); const originalText = submitBtn.innerHTML; submitBtn.disabled = true; submitBtn.innerHTML = ' 注册中...'; // Password strength validation if (password.length < 8) { throw new Error('密码长度必须至少为8个字符'); } if (!/[A-Z]/.test(password)) { throw new Error('密码必须包含至少一个大写字母'); } if (!/[0-9]/.test(password)) { throw new Error('密码必须包含至少一个数字'); } if (!window.supabaseClient) { throw new Error('Authentication system not initialized'); } const { data, error } = await window.supabaseClient.auth.signUp({ email: email, password: password, options: { emailRedirectTo: window.location.origin + '/index.html', data: { registered_at: new Date().toISOString() } } }); if (error) throw error; if (data?.user?.identities?.length === 0) { showAlert('该邮箱已注册,请直接登录。', 'warning'); showLoginForm(); return null; } // Show success message with more details showAlert(`注册成功!我们已向 ${email} 发送了确认邮件,请查收并点击确认链接完成注册。`, 'success'); showLoginForm(); return data.user; } catch (error) { console.error('Error registering:', error.message); let errorMessage = '注册失败'; // Provide user-friendly error messages if (error.message.includes('already registered')) { errorMessage = '该邮箱已注册,请直接登录或使用其他邮箱'; } else if (error.message.includes('password')) { errorMessage = error.message; } else if (error.message.includes('valid email')) { errorMessage = '请输入有效的电子邮箱地址'; } else { errorMessage = `注册失败: ${error.message}`; } showAlert(errorMessage, 'danger'); return null; } finally { // Reset button state const submitBtn = document.querySelector('#signup-form button[type="submit"]'); if (submitBtn) { submitBtn.disabled = false; submitBtn.innerHTML = '注册'; } } } // Reset password async function resetPassword(email) { try { // Show loading state const submitBtn = document.querySelector('#reset-form button[type="submit"]'); submitBtn.disabled = true; submitBtn.innerHTML = ' 发送中...'; // Validate email format const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { throw new Error('请输入有效的电子邮箱地址'); } if (!window.supabaseClient) { throw new Error('Authentication system not initialized'); } const { data, error } = await window.supabaseClient.auth.resetPasswordForEmail(email, { redirectTo: window.location.origin + '/index.html' }); if (error) throw error; showAlert(`密码重置链接已发送到 ${email},请查收并点击链接重置密码。`, 'success'); showLoginForm(); } catch (error) { console.error('Error resetting password:', error.message); let errorMessage = '密码重置失败'; // Provide user-friendly error messages if (error.message.includes('email')) { errorMessage = '请输入有效的电子邮箱地址'; } else { errorMessage = `密码重置失败: ${error.message}`; } showAlert(errorMessage, 'danger'); } finally { // Reset button state const submitBtn = document.querySelector('#reset-form button[type="submit"]'); if (submitBtn) { submitBtn.disabled = false; submitBtn.innerHTML = '发送重置链接'; } } } // Logout user async function logoutUser() { try { // Show loading state on logout button if exists const logoutBtn = document.getElementById('logout-button'); if (logoutBtn) { logoutBtn.disabled = true; const originalText = logoutBtn.innerHTML; logoutBtn.innerHTML = ' 退出中...'; } if (!window.supabaseClient) { throw new Error('Authentication system not initialized'); } const { error } = await window.supabaseClient.auth.signOut(); if (error) throw error; // Clear any user data from localStorage localStorage.removeItem('userEmail'); updateUserInterface(null); showAlert('您已成功退出登录。', 'info'); // Redirect to home page if on dashboard or protected page const protectedPages = ['dashboard.html', 'profile.html', 'settings.html']; const currentPage = window.location.pathname.split('/').pop(); if (protectedPages.some(page => currentPage.includes(page))) { setTimeout(() => { window.location.href = 'index.html'; }, 1000); } } catch (error) { console.error('Error logging out:', error.message); showAlert(`退出登录失败: ${error.message}`, 'danger'); } finally { // Reset logout button if exists const logoutBtn = document.getElementById('logout-button'); if (logoutBtn) { logoutBtn.disabled = false; logoutBtn.innerHTML = '退出登录'; } } } // Show alert message function showAlert(message, type = 'info') { const alertContainer = document.createElement('div'); alertContainer.className = `alert alert-${type} alert-dismissible fade show position-fixed top-0 start-50 translate-middle-x mt-3`; alertContainer.style.zIndex = '9999'; alertContainer.innerHTML = ` ${message} `; document.body.appendChild(alertContainer); // Auto dismiss after 5 seconds setTimeout(() => { alertContainer.classList.remove('show'); setTimeout(() => alertContainer.remove(), 300); }, 5000); } // DOM内容加载完成后的事件处理 // 注意:主要的初始化已移至文档顶部,这里专注于UI交互 document.addEventListener('DOMContentLoaded', async () => { console.log('设置认证UI事件监听器...'); // 异步检查用户登录状态 setTimeout(async () => { // 检查用户是否已登录 const user = await checkUser(); // 添加会话过期检查 if (user) { console.log('用户已登录,设置会话监控...'); // 每分钟检查会话有效性 setInterval(async () => { if (!window.supabaseClient) { console.error('会话检查失败: Supabase客户端未初始化'); return; } try { const { data: { session }, error } = await window.supabaseClient.auth.getSession(); if (error) { console.error('获取会话时出错:', error.message); return; } if (!session) { // 会话过期,显示通知并更新UI console.log('会话已过期'); showAlert('您的会话已过期,请重新登录', 'warning'); updateUserInterface(null); } } catch (e) { console.error('检查会话时出错:', e); } }, 60000); // 每分钟检查一次 } // 增强的认证状态变化监听器 if (window.supabaseClient) { try { const { data: { subscription } } = window.supabaseClient.auth.onAuthStateChange((event, session) => { console.log('认证状态变化:', event); if (event === 'SIGNED_IN' && session) { console.log('用户已登录:', session.user.email); updateUserInterface(session.user); // 存储上次登录时间 localStorage.setItem('lastLoginTime', new Date().toISOString()); // 隐藏认证模态框 const modal = document.getElementById('authModal'); if (modal && typeof bootstrap !== 'undefined') { const bsModal = bootstrap.Modal.getInstance(modal); if (bsModal) bsModal.hide(); } showAlert('登录成功!', 'success'); } else if (event === 'SIGNED_OUT') { console.log('用户已退出登录'); updateUserInterface(null); localStorage.removeItem('lastLoginTime'); } else if (event === 'PASSWORD_RECOVERY') { showAlert('请设置新密码', 'info'); } else if (event === 'USER_UPDATED') { showAlert('您的账户信息已更新', 'success'); updateUserInterface(session.user); } else if (event === 'INITIAL_SESSION') { // 处理初始会话状态 if (session) { console.log('初始会话已加载,用户已登录:', session.user.email); updateUserInterface(session.user); } else { console.log('初始会话已加载,用户未登录'); updateUserInterface(null); } } }); console.log('认证状态监听器已设置'); } catch (error) { console.error('设置认证状态监听器时出错:', error); } } else { console.error('无法设置认证状态监听器: Supabase客户端未初始化'); // 尝试修复 setTimeout(() => { if (typeof supabase !== 'undefined' && !window.supabaseClient) { console.log('尝试恢复Supabase客户端...'); window.supabaseClient = initializeSupabase(); } }, 2000); } }, 500); // 短暂延迟以确保页面完全加载 // 登录按钮点击事件 - 添加错误处理 if (loginButton) { loginButton.addEventListener('click', () => { try { console.log('显示登录表单'); showLoginForm(); // 检查模态框实例 if (typeof authModal === 'undefined' || !authModal) { console.warn('模态框实例不存在,尝试重新初始化'); // 尝试重新创建Bootstrap模态框实例 const modalElement = document.getElementById('authModal'); if (modalElement && typeof bootstrap !== 'undefined') { authModal = new bootstrap.Modal(modalElement); } else { throw new Error('无法初始化认证模态框'); } } authModal.show(); } catch (error) { console.error('显示登录表单时出错:', error); showAlert('登录功能暂时不可用,请刷新页面', 'danger'); } }); } else { console.warn('登录按钮未找到'); } // 注册按钮点击事件 - 添加错误处理 if (signupButton) { signupButton.addEventListener('click', () => { try { console.log('显示注册表单'); showSignupForm(); // 检查模态框实例 if (typeof authModal === 'undefined' || !authModal) { console.warn('模态框实例不存在,尝试重新初始化'); // 尝试重新创建Bootstrap模态框实例 const modalElement = document.getElementById('authModal'); if (modalElement && typeof bootstrap !== 'undefined') { authModal = new bootstrap.Modal(modalElement); } else { throw new Error('无法初始化认证模态框'); } } authModal.show(); } catch (error) { console.error('显示注册表单时出错:', error); showAlert('注册功能暂时不可用,请刷新页面', 'danger'); } }); } else { console.warn('注册按钮未找到'); } // Logout button click if (logoutButton) { logoutButton.addEventListener('click', (e) => { e.preventDefault(); logoutUser(); }); } // Switch to signup form if (switchToSignup) { switchToSignup.addEventListener('click', (e) => { e.preventDefault(); showSignupForm(); }); } // Switch to login form if (switchToLogin) { switchToLogin.addEventListener('click', (e) => { e.preventDefault(); showLoginForm(); }); } // Forgot password link if (forgotPassword) { forgotPassword.addEventListener('click', (e) => { e.preventDefault(); showResetForm(); }); } // Back to login link if (backToLogin) { backToLogin.addEventListener('click', (e) => { e.preventDefault(); showLoginForm(); }); } // Login form submit if (loginForm) { loginForm.addEventListener('submit', async (e) => { e.preventDefault(); const email = document.getElementById('login-email').value; const password = document.getElementById('login-password').value; await loginUser(email, password); }); } // Signup form submit if (signupForm) { signupForm.addEventListener('submit', async (e) => { e.preventDefault(); const email = document.getElementById('signup-email').value; const password = document.getElementById('signup-password').value; const confirmPassword = document.getElementById('signup-password-confirm').value; if (password !== confirmPassword) { showAlert('密码不匹配,请重新输入。', 'danger'); return; } await registerUser(email, password); }); } // Reset form submit if (resetForm) { resetForm.addEventListener('submit', async (e) => { e.preventDefault(); const email = document.getElementById('reset-email').value; await resetPassword(email); }); } // Get started button with improved session check const getStartedButton = document.getElementById('get-started-button'); if (getStartedButton) { getStartedButton.addEventListener('click', async () => { try { const { data: { user }, error } = await window.supabaseClient.auth.getUser(); if (error) throw error; if (user) { // Add loading state getStartedButton.disabled = true; getStartedButton.innerHTML = ' 正在跳转...'; // Redirect to dashboard window.location.href = 'dashboard.html'; } else { showLoginForm(); authModal.show(); } } catch (error) { console.error('Error checking user session:', error.message); showLoginForm(); authModal.show(); } }); } // Add password visibility toggle for login and signup forms const togglePasswordVisibility = (inputId, toggleId) => { const passwordInput = document.getElementById(inputId); const toggleButton = document.getElementById(toggleId); if (passwordInput && toggleButton) { toggleButton.addEventListener('click', () => { const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password'; passwordInput.setAttribute('type', type); // Update icon if (type === 'text') { toggleButton.innerHTML = ''; toggleButton.setAttribute('title', '隐藏密码'); } else { toggleButton.innerHTML = ''; toggleButton.setAttribute('title', '显示密码'); } }); } }; // Apply password visibility toggle to login and signup forms togglePasswordVisibility('login-password', 'toggle-login-password'); togglePasswordVisibility('signup-password', 'toggle-signup-password'); togglePasswordVisibility('signup-password-confirm', 'toggle-signup-password-confirm'); });