You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
15 KiB
449 lines
15 KiB
// 用户资料页面JavaScript
|
|
(function() {
|
|
'use strict';
|
|
|
|
// 页面初始化
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initProfilePage();
|
|
});
|
|
|
|
function initProfilePage() {
|
|
bindFormEvents();
|
|
bindInputValidation();
|
|
showInitialMessage();
|
|
initTabs();
|
|
}
|
|
|
|
// 绑定表单事件
|
|
function bindFormEvents() {
|
|
const profileForm = document.getElementById('profileForm');
|
|
const passwordForm = document.getElementById('passwordForm');
|
|
|
|
console.log('Profile form found:', !!profileForm);
|
|
console.log('Password form found:', !!passwordForm);
|
|
|
|
if (profileForm) {
|
|
profileForm.addEventListener('submit', handleProfileUpdate);
|
|
console.log('Profile form event listener added');
|
|
}
|
|
|
|
if (passwordForm) {
|
|
passwordForm.addEventListener('submit', handlePasswordChange);
|
|
console.log('Password form event listener added');
|
|
}
|
|
}
|
|
|
|
// 处理用户资料更新
|
|
async function handleProfileUpdate(event) {
|
|
event.preventDefault();
|
|
|
|
const form = event.target;
|
|
const submitBtn = form.querySelector('button[type="submit"]');
|
|
const originalText = submitBtn.textContent;
|
|
|
|
try {
|
|
setButtonLoading(submitBtn, true);
|
|
|
|
const formData = new FormData(form);
|
|
const data = Object.fromEntries(formData.entries());
|
|
|
|
// 验证必填字段
|
|
if (!validateProfileData(data)) {
|
|
return;
|
|
}
|
|
|
|
const response = await fetch('/profile/update', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
showMessage('资料更新成功!', 'success', 'profileForm');
|
|
updateUserInfoDisplay(result.user);
|
|
} else {
|
|
throw new Error(result.message || '更新失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
showMessage(error.message || '更新失败,请重试', 'error', 'profileForm');
|
|
console.error('Profile update error:', error);
|
|
} finally {
|
|
setButtonLoading(submitBtn, false, originalText);
|
|
}
|
|
}
|
|
|
|
// 处理密码修改
|
|
async function handlePasswordChange(event) {
|
|
event.preventDefault();
|
|
|
|
const form = event.target;
|
|
const submitBtn = form.querySelector('button[type="submit"]');
|
|
const originalText = submitBtn.textContent;
|
|
|
|
try {
|
|
setButtonLoading(submitBtn, true);
|
|
|
|
const formData = new FormData(form);
|
|
const data = Object.fromEntries(formData.entries());
|
|
|
|
if (!validatePasswordData(data)) {
|
|
return;
|
|
}
|
|
|
|
const response = await fetch('/profile/change-password', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
showMessage('密码修改成功!', 'success', 'passwordForm');
|
|
form.reset();
|
|
} else {
|
|
throw new Error(result.message || '密码修改失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
showMessage(error.message || '密码修改失败,请重试', 'error', 'passwordForm');
|
|
console.error('Password change error:', error);
|
|
} finally {
|
|
setButtonLoading(submitBtn, false, originalText);
|
|
}
|
|
}
|
|
|
|
// 验证用户资料数据
|
|
function validateProfileData(data) {
|
|
if (!data.username.trim()) {
|
|
showMessage('用户名不能为空', 'error', 'profileForm');
|
|
return false;
|
|
}
|
|
|
|
if (data.username.length < 3) {
|
|
showMessage('用户名长度不能少于3位', 'error', 'profileForm');
|
|
return false;
|
|
}
|
|
|
|
if (data.email && !isValidEmail(data.email)) {
|
|
showMessage('请输入有效的邮箱地址', 'error', 'profileForm');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 验证密码数据
|
|
function validatePasswordData(data) {
|
|
const { oldPassword, newPassword, confirmPassword } = data;
|
|
|
|
if (!oldPassword || !newPassword || !confirmPassword) {
|
|
showMessage('请填写所有密码字段', 'error', 'passwordForm');
|
|
return false;
|
|
}
|
|
|
|
if (newPassword.length < 6) {
|
|
showMessage('新密码长度不能少于6位', 'error', 'passwordForm');
|
|
return false;
|
|
}
|
|
|
|
if (newPassword !== confirmPassword) {
|
|
showMessage('新密码与确认密码不匹配', 'error', 'passwordForm');
|
|
return false;
|
|
}
|
|
|
|
if (oldPassword === newPassword) {
|
|
showMessage('新密码不能与当前密码相同', 'error', 'passwordForm');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 绑定输入验证
|
|
function bindInputValidation() {
|
|
const inputs = document.querySelectorAll('.form-input, .form-textarea');
|
|
|
|
inputs.forEach(input => {
|
|
input.addEventListener('blur', function() {
|
|
validateField(this);
|
|
});
|
|
|
|
input.addEventListener('input', function() {
|
|
clearFieldError(this);
|
|
});
|
|
});
|
|
}
|
|
|
|
// 验证单个字段
|
|
function validateField(field) {
|
|
const value = field.value.trim();
|
|
const fieldName = field.name;
|
|
|
|
clearFieldError(field);
|
|
|
|
let isValid = true;
|
|
let errorMessage = '';
|
|
|
|
switch (fieldName) {
|
|
case 'username':
|
|
if (!value) {
|
|
isValid = false;
|
|
errorMessage = '用户名不能为空';
|
|
} else if (value.length < 3) {
|
|
isValid = false;
|
|
errorMessage = '用户名长度不能少于3位';
|
|
}
|
|
break;
|
|
|
|
case 'email':
|
|
if (value && !isValidEmail(value)) {
|
|
isValid = false;
|
|
errorMessage = '请输入有效的邮箱地址';
|
|
}
|
|
break;
|
|
|
|
case 'newPassword':
|
|
if (value && value.length < 6) {
|
|
isValid = false;
|
|
errorMessage = '密码长度不能少于6位';
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!isValid) {
|
|
showFieldError(field, errorMessage);
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
|
|
// 显示字段错误
|
|
function showFieldError(field, message) {
|
|
field.classList.add('error');
|
|
|
|
let errorElement = field.parentNode.querySelector('.error-message');
|
|
if (!errorElement) {
|
|
errorElement = document.createElement('div');
|
|
errorElement.className = 'error-message';
|
|
field.parentNode.appendChild(errorElement);
|
|
}
|
|
|
|
errorElement.textContent = message;
|
|
errorElement.classList.add('show');
|
|
}
|
|
|
|
// 清除字段错误
|
|
function clearFieldError(field) {
|
|
field.classList.remove('error');
|
|
|
|
const errorElement = field.parentNode.querySelector('.error-message');
|
|
if (errorElement) {
|
|
errorElement.classList.remove('show');
|
|
}
|
|
}
|
|
|
|
// 验证邮箱格式
|
|
function isValidEmail(email) {
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
return emailRegex.test(email);
|
|
}
|
|
|
|
// 设置按钮加载状态
|
|
function setButtonLoading(button, loading, originalText = null) {
|
|
if (loading) {
|
|
button.disabled = true;
|
|
button.textContent = '处理中...';
|
|
button.classList.add('loading');
|
|
} else {
|
|
button.disabled = false;
|
|
button.textContent = originalText || button.textContent;
|
|
button.classList.remove('loading');
|
|
}
|
|
}
|
|
|
|
// 显示消息
|
|
function showMessage(message, type = 'info', formId = null) {
|
|
console.log('showMessage called with:', { message, type, formId });
|
|
removeExistingMessages();
|
|
|
|
let targetContainer;
|
|
if (formId === 'profileForm') {
|
|
targetContainer = document.querySelector('#profileForm .message-container');
|
|
console.log('Looking for profileForm message container:', !!targetContainer);
|
|
} else if (formId === 'passwordForm') {
|
|
targetContainer = document.querySelector('#passwordForm .message-container');
|
|
console.log('Looking for passwordForm message container:', !!targetContainer);
|
|
} else {
|
|
// 如果没有指定表单,使用默认容器
|
|
targetContainer = document.querySelector('.profile-content');
|
|
console.log('Using default container:', !!targetContainer);
|
|
}
|
|
|
|
if (!targetContainer) {
|
|
console.warn('Message container not found for formId:', formId);
|
|
console.warn('Available containers:', document.querySelectorAll('.message-container'));
|
|
// 尝试使用备用容器
|
|
targetContainer = document.querySelector('.message-container');
|
|
if (!targetContainer) {
|
|
console.error('No message container found anywhere');
|
|
return;
|
|
}
|
|
}
|
|
|
|
console.log('Target container found:', targetContainer);
|
|
|
|
const messageElement = document.createElement('div');
|
|
messageElement.className = `message ${type} show`;
|
|
|
|
const messageText = document.createElement('span');
|
|
messageText.textContent = message;
|
|
messageElement.appendChild(messageText);
|
|
|
|
const closeButton = document.createElement('button');
|
|
closeButton.className = 'message-close';
|
|
closeButton.type = 'button';
|
|
closeButton.innerHTML = '×';
|
|
closeButton.onclick = function() {
|
|
messageElement.remove();
|
|
};
|
|
messageElement.appendChild(closeButton);
|
|
|
|
targetContainer.appendChild(messageElement);
|
|
console.log('Message added to container');
|
|
|
|
// 5秒后自动隐藏
|
|
setTimeout(() => {
|
|
if (messageElement.parentNode) {
|
|
messageElement.remove();
|
|
}
|
|
}, 5000);
|
|
}
|
|
|
|
// 关闭指定消息
|
|
function closeMessage(messageId) {
|
|
const messageElement = document.getElementById(messageId);
|
|
if (messageElement) {
|
|
messageElement.remove();
|
|
}
|
|
}
|
|
|
|
// 移除现有消息
|
|
function removeExistingMessages() {
|
|
const existingMessages = document.querySelectorAll('.message');
|
|
existingMessages.forEach(msg => msg.remove());
|
|
}
|
|
|
|
// 显示初始消息
|
|
function showInitialMessage() {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const msg = urlParams.get('msg');
|
|
const msgType = urlParams.get('type') || 'info';
|
|
|
|
if (msg) {
|
|
showMessage(decodeURIComponent(msg), msgType);
|
|
const newUrl = window.location.pathname;
|
|
window.history.replaceState({}, document.title, newUrl);
|
|
}
|
|
}
|
|
|
|
// 更新用户信息显示
|
|
function updateUserInfoDisplay(user) {
|
|
const infoItems = document.querySelectorAll('.info-value');
|
|
infoItems.forEach(item => {
|
|
const label = item.previousElementSibling.textContent;
|
|
if (label.includes('最后更新')) {
|
|
item.textContent = new Date().toLocaleDateString('zh-CN');
|
|
}
|
|
});
|
|
}
|
|
|
|
// 重置表单
|
|
function resetForm() {
|
|
const form = document.getElementById('profileForm');
|
|
if (form) {
|
|
form.reset();
|
|
const inputs = form.querySelectorAll('.form-input, .form-textarea');
|
|
inputs.forEach(input => clearFieldError(input));
|
|
showMessage('表单已重置', 'info');
|
|
}
|
|
}
|
|
|
|
// 重置密码表单
|
|
function resetPasswordForm() {
|
|
console.log('resetPasswordForm called');
|
|
const form = document.getElementById('passwordForm');
|
|
console.log('Password form found:', !!form);
|
|
|
|
if (form) {
|
|
form.reset();
|
|
const inputs = form.querySelectorAll('.form-input');
|
|
inputs.forEach(input => clearFieldError(input));
|
|
|
|
// 查找消息容器
|
|
const messageContainer = form.querySelector('.message-container');
|
|
console.log('Message container found:', !!messageContainer);
|
|
|
|
showMessage('密码表单已清空', 'info', 'passwordForm');
|
|
} else {
|
|
console.error('Password form not found');
|
|
}
|
|
}
|
|
|
|
// 初始化标签页
|
|
function initTabs() {
|
|
const tabBtns = document.querySelectorAll('.tab-btn');
|
|
const tabPanes = document.querySelectorAll('.tab-pane');
|
|
|
|
console.log('Initializing tabs...');
|
|
console.log('Tab buttons found:', tabBtns.length);
|
|
console.log('Tab panes found:', tabPanes.length);
|
|
|
|
if (tabBtns.length === 0 || tabPanes.length === 0) {
|
|
console.warn('Tab elements not found');
|
|
return;
|
|
}
|
|
|
|
tabBtns.forEach(btn => {
|
|
btn.addEventListener('click', function() {
|
|
const targetTab = this.getAttribute('data-tab');
|
|
console.log('Tab clicked:', targetTab); // 调试日志
|
|
|
|
// 移除所有活动状态
|
|
tabBtns.forEach(b => b.classList.remove('active'));
|
|
tabPanes.forEach(p => p.classList.remove('active'));
|
|
|
|
// 添加活动状态到当前标签
|
|
this.classList.add('active');
|
|
const targetPane = document.getElementById(targetTab + '-tab');
|
|
if (targetPane) {
|
|
targetPane.classList.add('active');
|
|
console.log('Tab pane activated:', targetTab + '-tab'); // 调试日志
|
|
|
|
// 重新绑定表单事件,确保新显示的Tab中的表单能正常工作
|
|
setTimeout(() => {
|
|
bindFormEvents();
|
|
}, 100);
|
|
} else {
|
|
console.error('Target tab pane not found:', targetTab + '-tab');
|
|
}
|
|
});
|
|
});
|
|
|
|
// 确保默认标签页是激活状态
|
|
const defaultTab = document.querySelector('.tab-btn.active');
|
|
const defaultPane = document.querySelector('.tab-pane.active');
|
|
if (defaultTab && defaultPane) {
|
|
console.log('Default tab initialized:', defaultTab.getAttribute('data-tab'));
|
|
}
|
|
}
|
|
|
|
// 导出函数供HTML调用
|
|
window.resetForm = resetForm;
|
|
window.resetPasswordForm = resetPasswordForm;
|
|
window.closeMessage = closeMessage;
|
|
|
|
})();
|
|
|