/**
* 官网用户认证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
};
})();