Files
Docker-Proxy/hubcmdui/web/js/userCenter.js

333 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 用户中心管理模块
*/
// 获取用户信息
async function getUserInfo() {
try {
// 先检查是否已登录
const sessionResponse = await fetch('/api/check-session');
const sessionData = await sessionResponse.json();
if (!sessionData.authenticated) {
// 用户未登录,不显示错误,静默返回
// console.log('用户未登录或会话无效,跳过获取用户信息');
return;
}
// 用户已登录,获取用户信息
// console.log('会话有效,尝试获取用户信息...');
const response = await fetch('/api/user-info');
if (!response.ok) {
// 检查是否是认证问题
if (response.status === 401) {
// console.log('会话已过期,需要重新登录');
return;
}
throw new Error('获取用户信息失败');
}
const data = await response.json();
// console.log('获取到用户信息:', data);
// 更新顶部导航栏的用户名
const currentUsername = document.getElementById('currentUsername');
if (currentUsername) {
currentUsername.textContent = data.username || '未知用户';
}
// 更新统计卡片数据
const loginCountElement = document.getElementById('loginCount');
if (loginCountElement) {
loginCountElement.textContent = data.loginCount || '0';
}
const accountAgeElement = document.getElementById('accountAge');
if (accountAgeElement) {
accountAgeElement.textContent = data.accountAge ? `${data.accountAge}` : '0天';
}
const lastLoginElement = document.getElementById('lastLogin');
if (lastLoginElement) {
let lastLogin = data.lastLogin || '未知';
// 检查是否包含 "今天" 字样,添加样式
if (lastLogin.includes('今天')) {
lastLoginElement.innerHTML = `<span class="today-login">${lastLogin}</span>`;
} else {
lastLoginElement.textContent = lastLogin;
}
}
} catch (error) {
// console.error('获取用户信息失败:', error);
// 不显示错误通知,只在控制台记录错误
}
}
// 修改密码
async function changePassword(event) {
if (event) {
event.preventDefault();
}
const form = document.getElementById('changePasswordForm');
const currentPassword = form.querySelector('#ucCurrentPassword').value;
const newPassword = form.querySelector('#ucNewPassword').value;
const confirmPassword = form.querySelector('#ucConfirmPassword').value;
// 验证表单
if (!currentPassword || !newPassword || !confirmPassword) {
return core.showAlert('所有字段都不能为空', 'error');
}
if (newPassword !== confirmPassword) {
return core.showAlert('两次输入的新密码不一致', 'error');
}
// 密码复杂度检查
if (!isPasswordComplex(newPassword)) {
return core.showAlert('密码必须包含至少1个字母、1个数字和1个特殊字符长度在8-16位之间', 'error');
}
// 显示加载状态
const submitButton = form.querySelector('button[type="submit"]');
const originalButtonText = submitButton.innerHTML;
submitButton.disabled = true;
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 提交中...';
try {
const response = await fetch('/api/change-password', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
currentPassword,
newPassword
})
});
// 无论成功与否,去除加载状态
submitButton.disabled = false;
submitButton.innerHTML = originalButtonText;
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || '修改密码失败');
}
// 清空表单
form.reset();
// 设置倒计时并显示
let countDown = 5;
Swal.fire({
title: '密码修改成功',
html: `您的密码已成功修改,系统将在 <b>${countDown}</b> 秒后自动退出,请使用新密码重新登录。`,
icon: 'success',
timer: countDown * 1000,
timerProgressBar: true,
didOpen: () => {
const content = Swal.getHtmlContainer();
const timerInterval = setInterval(() => {
countDown--;
if (content) {
const b = content.querySelector('b');
if (b) {
b.textContent = countDown > 0 ? countDown : 0;
}
}
if (countDown <= 0) clearInterval(timerInterval);
}, 1000);
},
allowOutsideClick: false, // 禁止外部点击关闭
showConfirmButton: true, // 重新显示确认按钮
confirmButtonText: '确定' // 设置按钮文本
}).then((result) => {
// 当计时器结束或弹窗被关闭时 (包括点击确定按钮)
if (result.dismiss === Swal.DismissReason.timer || result.isConfirmed) {
// console.log('计时器结束或手动确认,执行登出');
auth.logout();
}
});
} catch (error) {
// console.error('修改密码失败:', error);
core.showAlert('修改密码失败: ' + error.message, 'error');
}
}
// 验证密码复杂度
function isPasswordComplex(password) {
// 至少包含1个字母、1个数字和1个特殊字符长度在8-16位之间
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[.,\-_+=()[\]{}|\\;:'"<>?/@$!%*#?&])[A-Za-z\d.,\-_+=()[\]{}|\\;:'"<>?/@$!%*#?&]{8,16}$/;
return passwordRegex.test(password);
}
// 检查密码强度
function checkUcPasswordStrength() {
const password = document.getElementById('ucNewPassword').value;
const strengthSpan = document.getElementById('ucPasswordStrength');
const strengthBar = document.getElementById('strengthBar');
if (!password) {
strengthSpan.textContent = '';
if (strengthBar) strengthBar.style.width = '0%';
return;
}
let strength = 0;
let strengthText = '';
let strengthColor = '';
let strengthWidth = '0%';
// 长度检查
if (password.length >= 8) strength++;
if (password.length >= 12) strength++;
// 包含字母
if (/[A-Za-z]/.test(password)) strength++;
// 包含数字
if (/\d/.test(password)) strength++;
// 包含特殊字符
if (/[.,\-_+=()[\]{}|\\;:'"<>?/@$!%*#?&]/.test(password)) strength++;
// 根据强度设置文本和颜色
switch(strength) {
case 0:
case 1:
strengthText = '密码强度:非常弱';
strengthColor = '#FF4136';
strengthWidth = '20%';
break;
case 2:
strengthText = '密码强度:弱';
strengthColor = '#FF851B';
strengthWidth = '40%';
break;
case 3:
strengthText = '密码强度:中';
strengthColor = '#FFDC00';
strengthWidth = '60%';
break;
case 4:
strengthText = '密码强度:强';
strengthColor = '#2ECC40';
strengthWidth = '80%';
break;
case 5:
strengthText = '密码强度:非常强';
strengthColor = '#3D9970';
strengthWidth = '100%';
break;
}
// 用span元素包裹文本并设置为不换行
strengthSpan.innerHTML = `<span style="white-space: nowrap;">${strengthText}</span>`;
strengthSpan.style.color = strengthColor;
if (strengthBar) {
strengthBar.style.width = strengthWidth;
strengthBar.style.backgroundColor = strengthColor;
}
}
// 切换密码可见性
function togglePasswordVisibility(inputId) {
const passwordInput = document.getElementById(inputId);
const toggleBtn = passwordInput.nextElementSibling.querySelector('i');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
toggleBtn.classList.remove('fa-eye');
toggleBtn.classList.add('fa-eye-slash');
} else {
passwordInput.type = 'password';
toggleBtn.classList.remove('fa-eye-slash');
toggleBtn.classList.add('fa-eye');
}
}
// 刷新用户信息
function refreshUserInfo() {
// 显示刷新动画
Swal.fire({
title: '刷新中...',
html: '<i class="fas fa-sync-alt fa-spin"></i> 正在刷新用户信息',
showConfirmButton: false,
allowOutsideClick: false,
timer: 1500
});
// 调用获取用户信息
getUserInfo().then(() => {
// 更新页面上的用户名称
const usernameElement = document.getElementById('profileUsername');
const currentUsername = document.getElementById('currentUsername');
if (usernameElement && currentUsername) {
usernameElement.textContent = currentUsername.textContent || '管理员';
}
// 显示成功消息
Swal.fire({
title: '刷新成功',
icon: 'success',
timer: 1500,
showConfirmButton: false
});
}).catch(error => {
Swal.fire({
title: '刷新失败',
text: error.message || '无法获取最新用户信息',
icon: 'error',
timer: 2000,
showConfirmButton: false
});
});
}
// 初始化用户中心
function initUserCenter() {
// console.log('初始化用户中心');
// 获取用户信息
getUserInfo();
// 为用户中心按钮添加事件
const userCenterBtn = document.getElementById('userCenterBtn');
if (userCenterBtn) {
userCenterBtn.addEventListener('click', () => {
core.showSection('user-center');
});
}
}
// 加载用户统计信息
function loadUserStats() {
getUserInfo();
}
// 导出模块
const userCenter = {
init: function() {
// console.log('初始化用户中心模块...');
// 可以在这里调用初始化逻辑,也可以延迟到需要时调用
return Promise.resolve(); // 返回一个已解决的 Promise保持与其他模块一致
},
getUserInfo,
changePassword,
checkUcPasswordStrength,
initUserCenter,
loadUserStats,
isPasswordComplex,
togglePasswordVisibility,
refreshUserInfo
};
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', initUserCenter);
// 全局公开用户中心模块
window.userCenter = userCenter;