/** * 官网用户认证UI控制 * 处理登录弹窗、导航栏状态更新等 */ (function() { 'use strict'; // 模态框实例 let loginModal = null; let registerModal = null; // 防抖标志 let isLoginProcessing = false; /** * 初始化认证UI */ function initAuthUI() { // 初始化Bootstrap模态框 const loginModalElement = document.getElementById('loginModal'); if (loginModalElement) { loginModal = new bootstrap.Modal(loginModalElement); } const registerModalElement = document.getElementById('registerModal'); if (registerModalElement) { registerModal = new bootstrap.Modal(registerModalElement); } // 绑定事件 bindEvents(); // 更新UI状态 updateUIState(); // 检查注册状态并更新UI checkRegistrationStatus(); } /** * 绑定事件 */ function bindEvents() { // 桌面端登录按钮 const loginBtn = document.getElementById('loginBtn'); if (loginBtn) { loginBtn.addEventListener('click', showLoginModal); } // 移动端登录按钮 const mobileLoginBtn = document.getElementById('mobileLoginBtn'); if (mobileLoginBtn) { mobileLoginBtn.addEventListener('click', showLoginModal); } // 桌面端登出按钮 const logoutBtn = document.getElementById('logoutBtn'); if (logoutBtn) { logoutBtn.addEventListener('click', handleLogout); } // 移动端登出按钮 const mobileLogoutBtn = document.getElementById('mobileLogoutBtn'); if (mobileLogoutBtn) { mobileLogoutBtn.addEventListener('click', handleLogout); } // 登录按钮点击事件 const loginSubmitBtn = document.getElementById('loginSubmitBtn'); if (loginSubmitBtn) { loginSubmitBtn.addEventListener('click', function(e) { e.preventDefault(); handleLogin(); }); } // 登录表单提交(回车键支持) const loginForm = document.getElementById('loginForm'); if (loginForm) { loginForm.addEventListener('submit', function(e) { e.preventDefault(); handleLogin(); }); } // 注册表单提交 const registerSubmitBtn = document.getElementById('registerSubmitBtn'); if (registerSubmitBtn) { registerSubmitBtn.addEventListener('click', handleRegister); } // 回车键提交注册表单 const registerForm = document.getElementById('registerForm'); if (registerForm) { registerForm.addEventListener('submit', function(e) { e.preventDefault(); handleRegister(); }); } // 切换到注册 const switchToRegister = document.getElementById('switchToRegister'); if (switchToRegister) { switchToRegister.addEventListener('click', function(e) { e.preventDefault(); loginModal.hide(); showRegisterModal(); }); } // 切换到登录 const switchToLogin = document.getElementById('switchToLogin'); if (switchToLogin) { switchToLogin.addEventListener('click', function(e) { e.preventDefault(); registerModal.hide(); showLoginModal(); }); } } /** * 显示登录模态框 */ function showLoginModal() { const loginModalElement = document.getElementById('loginModal'); if (!loginModalElement) { console.error('登录模态框元素未找到'); return; } // 使用 getOrCreateInstance 确保总是有有效的实例 loginModal = bootstrap.Modal.getOrCreateInstance(loginModalElement); // 清空表单和错误提示(仅在模态框关闭状态下清空) const usernameInput = document.getElementById('loginUsername'); const passwordInput = document.getElementById('loginPassword'); const errorDiv = document.getElementById('loginError'); // 检查模态框是否已经显示 const isModalVisible = loginModalElement.classList.contains('show'); if (!isModalVisible) { // 模态框未显示,清空表单和错误 if (usernameInput) usernameInput.value = ''; if (passwordInput) passwordInput.value = ''; if (errorDiv) errorDiv.style.display = 'none'; } loginModal.show(); } /** * 显示注册模态框 */ function showRegisterModal() { const registerModalElement = document.getElementById('registerModal'); if (!registerModalElement) { console.error('注册模态框元素未找到'); return; } // 使用 getOrCreateInstance 确保总是有有效的实例 registerModal = bootstrap.Modal.getOrCreateInstance(registerModalElement); // 清空表单 const usernameInput = document.getElementById('registerUsername'); const passwordInput = document.getElementById('registerPassword'); const passwordConfirmInput = document.getElementById('registerPasswordConfirm'); const errorDiv = document.getElementById('registerError'); if (usernameInput) usernameInput.value = ''; if (passwordInput) passwordInput.value = ''; if (passwordConfirmInput) passwordConfirmInput.value = ''; if (errorDiv) errorDiv.style.display = 'none'; registerModal.show(); } /** * 处理登录 */ async function handleLogin() { // 防抖检查 if (isLoginProcessing) { console.log('[登录] 正在处理中,忽略重复调用'); return; } const username = document.getElementById('loginUsername').value.trim(); const password = document.getElementById('loginPassword').value; const errorDiv = document.getElementById('loginError'); const submitBtn = document.getElementById('loginSubmitBtn'); // 验证输入 if (!username || !password) { showError('请输入用户名和密码'); return; } // 设置处理标志 isLoginProcessing = true; // 禁用按钮 submitBtn.disabled = true; submitBtn.innerHTML = '登录中...'; try { // 调用登录API const result = await webAuth.login(username, password); if (result.success) { // 登录成功 hideError(); // 强制关闭登录框 const loginModalElement = document.getElementById('loginModal'); if (loginModalElement) { // 方法1: 使用Bootstrap实例关闭 const modalInstance = bootstrap.Modal.getInstance(loginModalElement); if (modalInstance) { modalInstance.hide(); } // 方法2: 移除所有模态框相关的类和属性(备用方案) setTimeout(() => { loginModalElement.classList.remove('show'); loginModalElement.style.display = 'none'; loginModalElement.setAttribute('aria-hidden', 'true'); loginModalElement.removeAttribute('aria-modal'); // 移除背景遮罩 const backdrop = document.querySelector('.modal-backdrop'); if (backdrop) { backdrop.remove(); } // 恢复body滚动 document.body.classList.remove('modal-open'); document.body.style.overflow = ''; document.body.style.paddingRight = ''; }, 100); } // 更新UI状态 updateUIState(); // 获取并应用用户权限配置 await applyUserPermissionsAfterLogin(); // 启动Token有效性定期检查 if (typeof startTokenValidityCheck === 'function') { startTokenValidityCheck(); } // 显示成功提示 showToast('登录成功', 'success'); // 刷新页面数据 if (typeof loadGoods === 'function') { loadGoods(); } } else { // 登录失败 showError(result.error || '登录失败'); } } catch (error) { showError('网络错误,请稍后重试'); console.error('登录错误:', error); } finally { // 恢复按钮和标志 submitBtn.disabled = false; submitBtn.innerHTML = '登录'; isLoginProcessing = false; } } /** * 处理注册 */ async function handleRegister() { const username = document.getElementById('registerUsername').value.trim(); const password = document.getElementById('registerPassword').value; const passwordConfirm = document.getElementById('registerPasswordConfirm').value; const errorDiv = document.getElementById('registerError'); const submitBtn = document.getElementById('registerSubmitBtn'); // 验证输入 if (!username || !password || !passwordConfirm) { showRegisterError('请填写所有字段'); return; } if (username.length < 3 || username.length > 20) { showRegisterError('用户名长度必须在3-20个字符之间'); return; } if (password.length < 6 || password.length > 32) { showRegisterError('密码长度必须在6-32个字符之间'); return; } if (password !== passwordConfirm) { showRegisterError('两次密码不一致'); return; } // 禁用按钮 submitBtn.disabled = true; submitBtn.innerHTML = '注册中...'; try { // 调用注册API const result = await webAuth.register(username, password, passwordConfirm); if (result.success) { // 注册成功 hideRegisterError(); registerModal.hide(); // 更新UI状态 updateUIState(); // 获取并应用用户权限配置 await applyUserPermissionsAfterLogin(); // 显示成功提示 showToast('注册成功,欢迎使用!', 'success'); // 刷新页面数据 if (typeof loadGoods === 'function') { loadGoods(); } } else { // 注册失败 showRegisterError(result.error || '注册失败'); } } catch (error) { showRegisterError('网络错误,请稍后重试'); console.error('注册错误:', error); } finally { // 恢复按钮 submitBtn.disabled = false; submitBtn.innerHTML = '注册'; } } /** * 处理登出 */ async function handleLogout() { if (!confirm('确定要退出登录吗?')) { return; } try { // 停止Token有效性定期检查 if (typeof stopTokenValidityCheck === 'function') { stopTokenValidityCheck(); } await webAuth.logout(); // 更新UI状态 updateUIState(); // 显示成功提示 showToast('已退出登录', 'info'); // 刷新页面数据 if (typeof loadGoods === 'function') { loadGoods(); } } catch (error) { showToast('退出失败,请稍后重试', 'error'); console.error('登出错误:', error); } } /** * 更新UI状态 */ function updateUIState() { const isLoggedIn = webAuth.isLoggedIn(); const user = webAuth.getUserInfo(); // 桌面端 const loginBtn = document.getElementById('loginBtn'); const userInfoGroup = document.getElementById('userInfoGroup'); const usernameDisplay = document.getElementById('usernameDisplay'); if (isLoggedIn && user) { // 已登录状态 if (loginBtn) loginBtn.style.display = 'none'; if (userInfoGroup) userInfoGroup.style.display = 'inline-flex'; if (usernameDisplay) usernameDisplay.textContent = user.username; } else { // 未登录状态 if (loginBtn) loginBtn.style.display = 'inline-block'; if (userInfoGroup) userInfoGroup.style.display = 'none'; } // 移动端 const mobileLoginBtn = document.getElementById('mobileLoginBtn'); const mobileLogoutBtn = document.getElementById('mobileLogoutBtn'); if (isLoggedIn) { if (mobileLoginBtn) mobileLoginBtn.style.display = 'none'; if (mobileLogoutBtn) mobileLogoutBtn.style.display = 'inline-block'; } else { if (mobileLoginBtn) mobileLoginBtn.style.display = 'inline-block'; if (mobileLogoutBtn) mobileLogoutBtn.style.display = 'none'; } // 刷新控制面板 - 仅登录用户可见(Task #4) const refreshControlPanel = document.getElementById('refreshControlPanel'); if (refreshControlPanel) { refreshControlPanel.style.display = isLoggedIn ? 'block' : 'none'; } } /** * 显示错误信息 */ function showError(message) { let errorDiv = document.getElementById('loginError'); // 如果找不到errorDiv,尝试在模态框中创建一个 if (!errorDiv) { console.warn('[登录错误] loginError元素不存在,尝试创建...'); const modalBody = document.querySelector('#loginModal .modal-body'); if (modalBody) { // 检查是否已存在(可能ID不对) let existingAlert = modalBody.querySelector('.alert-danger'); if (existingAlert) { errorDiv = existingAlert; errorDiv.id = 'loginError'; } else { // 创建新的错误提示元素 errorDiv = document.createElement('div'); errorDiv.className = 'alert alert-danger'; errorDiv.id = 'loginError'; errorDiv.setAttribute('role', 'alert'); modalBody.insertBefore(errorDiv, modalBody.firstChild); } console.log('[登录错误] 已创建/修复loginError元素'); } else { // 最后的备选方案:使用alert弹窗 console.error('[登录错误] 无法找到模态框,使用alert显示错误'); alert('登录失败: ' + message); return; } } console.log('[登录错误] 显示错误:', message); errorDiv.textContent = message; errorDiv.style.display = 'block'; errorDiv.style.visibility = 'visible'; errorDiv.style.opacity = '1'; // 确保错误div可见(滚动到视图) errorDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); console.log('[登录错误] 错误div状态:', { display: errorDiv.style.display, visibility: errorDiv.style.visibility, opacity: errorDiv.style.opacity, textContent: errorDiv.textContent }); } /** * 隐藏错误信息 */ function hideError() { const errorDiv = document.getElementById('loginError'); if (errorDiv) { errorDiv.style.display = 'none'; errorDiv.textContent = ''; } } /** * 显示注册错误信息 */ function showRegisterError(message) { const errorDiv = document.getElementById('registerError'); if (errorDiv) { errorDiv.textContent = message; errorDiv.style.display = 'block'; } } /** * 隐藏注册错误信息 */ function hideRegisterError() { const errorDiv = document.getElementById('registerError'); if (errorDiv) { errorDiv.style.display = 'none'; } } /** * 显示Toast提示 */ function showToast(message, type = 'info') { // 如果页面有Toast容器,使用Toast // 否则使用alert if (typeof showMessage === 'function') { showMessage(message, type); } else { alert(message); } } /** * 登录成功后获取并应用用户权限配置 */ async function applyUserPermissionsAfterLogin() { try { // 获取权限配置 const permissionsData = await webAuth.getPermissions(); if (permissionsData && permissionsData.success) { const userLevel = permissionsData.user_level || 'guest'; const permissions = permissionsData.permissions; // 应用权限配置(需要main.js中的applyUserPermissions函数) if (typeof window.applyUserPermissions === 'function') { window.applyUserPermissions(permissions, userLevel); console.log('用户权限配置已应用', { userLevel, permissions }); } else { console.warn('applyUserPermissions函数未定义,将在加载商品数据时应用权限'); } } } catch (error) { console.error('获取权限配置失败:', error); // 不影响登录流程,权限配置将在加载商品数据时再次尝试 } } /** * 检查注册状态并更新UI */ async function checkRegistrationStatus() { console.debug('[注册状态检查] 开始检查...'); try { const response = await fetch('/api/v1/web-auth/registration-status'); console.debug('[注册状态检查] API响应状态:', response.status); const result = await response.json(); console.debug('[注册状态检查] API返回数据:', result); if (result && typeof result.enabled !== 'undefined') { const isEnabled = result.enabled; console.debug('[注册状态检查] 注册开关状态:', isEnabled); // 获取注册入口容器 const registerEntryContainer = document.getElementById('registerEntryContainer'); console.debug('[注册状态检查] 找到注册入口容器:', registerEntryContainer); // 根据注册状态显示/隐藏注册入口 if (registerEntryContainer) { if (isEnabled) { // 注册开启,显示注册入口 console.debug('[注册状态检查] 执行显示操作...'); registerEntryContainer.style.display = 'block'; console.debug('[注册状态检查] 注册入口已显示'); } else { // 注册关闭,隐藏注册入口 console.debug('[注册状态检查] 执行隐藏操作...'); registerEntryContainer.style.display = 'none'; console.debug('[注册状态检查] 注册入口已隐藏'); } } else { console.warn('[注册状态检查] 未找到注册入口容器 #registerEntryContainer'); } console.debug('[注册状态检查] 完成 - 状态:', isEnabled ? '开启' : '关闭'); } else { console.error('[注册状态检查] API返回数据格式错误:', result); } } catch (error) { console.error('[注册状态检查] 失败:', error); // 失败时默认隐藏注册入口(安全策略) const registerEntryContainer = document.getElementById('registerEntryContainer'); if (registerEntryContainer) { registerEntryContainer.style.display = 'none'; console.log('[注册状态检查] 失败后已隐藏注册入口'); } } } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAuthUI); } else { initAuthUI(); } // 导出到全局 window.authUI = { updateUIState: updateUIState, showLoginModal: showLoginModal, showRegisterModal: showRegisterModal, checkRegistrationStatus: checkRegistrationStatus }; })();