// 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');
});