taibai_shopping/app/static/js/admin_users.js
2025-07-09 05:22:28 +08:00

371 lines
12 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.

// 用户管理页面JavaScript
document.addEventListener('DOMContentLoaded', function() {
// 初始化
initializeUserManagement();
});
// 初始化用户管理功能
function initializeUserManagement() {
// 添加事件监听器
setupEventListeners();
// 初始化头像显示
initializeAvatars();
// 强制设置头像样式
forceAvatarStyles();
}
// 设置事件监听器
function setupEventListeners() {
// 搜索表单提交
const searchForm = document.querySelector('form[method="GET"]');
if (searchForm) {
searchForm.addEventListener('submit', function(e) {
// 可以在这里添加搜索前的验证
});
}
// 状态筛选变更
const statusSelect = document.getElementById('status');
if (statusSelect) {
statusSelect.addEventListener('change', function() {
// 自动提交表单
this.form.submit();
});
}
}
// 初始化头像显示
function initializeAvatars() {
const avatars = document.querySelectorAll('.user-avatar');
avatars.forEach(avatar => {
avatar.onerror = function() {
// 如果头像加载失败,替换为默认头像
this.style.display = 'none';
const placeholder = this.parentElement.querySelector('.user-avatar-placeholder');
if (placeholder) {
placeholder.style.display = 'flex';
}
};
});
}
// 强制设置头像样式覆盖Bootstrap
function forceAvatarStyles() {
// 设置表格中的头像样式
const tableAvatars = document.querySelectorAll('.table .user-avatar');
tableAvatars.forEach(avatar => {
setAvatarStyles(avatar, '48px');
});
}
// 设置单个头像样式
function setAvatarStyles(avatar, size) {
if (!avatar) return;
// 强制设置所有相关样式
avatar.style.setProperty('width', size, 'important');
avatar.style.setProperty('height', size, 'important');
avatar.style.setProperty('max-width', size, 'important');
avatar.style.setProperty('max-height', size, 'important');
avatar.style.setProperty('min-width', size, 'important');
avatar.style.setProperty('min-height', size, 'important');
avatar.style.setProperty('border-radius', '50%', 'important');
avatar.style.setProperty('object-fit', 'cover', 'important');
avatar.style.setProperty('border', '2px solid #f8f9fa', 'important');
avatar.style.setProperty('display', 'block', 'important');
avatar.style.setProperty('flex-shrink', '0', 'important');
avatar.style.setProperty('flex-grow', '0', 'important');
// 移除可能影响的Bootstrap类
avatar.classList.remove('img-fluid', 'img-responsive', 'img-thumbnail');
// 设置父元素样式
if (avatar.parentElement) {
avatar.parentElement.style.setProperty('width', size, 'important');
avatar.parentElement.style.setProperty('height', size, 'important');
avatar.parentElement.style.setProperty('overflow', 'hidden', 'important');
avatar.parentElement.style.setProperty('flex-shrink', '0', 'important');
avatar.parentElement.style.setProperty('flex-grow', '0', 'important');
}
}
// 查看用户详情
function viewUser(userId) {
// 显示模态框
const modal = new bootstrap.Modal(document.getElementById('userDetailModal'));
const content = document.getElementById('userDetailContent');
// 显示加载状态
content.innerHTML = `
<div class="loading">
<i class="bi bi-hourglass-split"></i>
<div>加载中...</div>
</div>
`;
modal.show();
// 发送AJAX请求获取用户详情
fetch(`/admin/users/${userId}/detail`)
.then(response => response.json())
.then(data => {
if (data.success) {
renderUserDetail(data.user);
// 立即强制设置头像样式
setTimeout(() => {
forceModalAvatarStyles();
}, 50);
// 再次确保样式正确应用
setTimeout(() => {
forceModalAvatarStyles();
}, 200);
} else {
showError('获取用户详情失败: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
showError('网络错误,请重试');
});
}
// 渲染用户详情
function renderUserDetail(user) {
const content = document.getElementById('userDetailContent');
content.innerHTML = `
<div class="user-detail">
<div class="row">
<div class="col-md-3 text-center">
<div class="user-avatar-large-wrapper">
${user.avatar_url ?
`<img src="${user.avatar_url}" alt="用户头像" class="avatar-large" id="modalAvatar">` :
`<div class="avatar-placeholder-large"><i class="bi bi-person"></i></div>`
}
</div>
<h5 class="mt-3">${user.nickname || user.username}</h5>
<span class="badge bg-${user.status === 1 ? 'success' : 'danger'}">
${user.status === 1 ? '正常' : '禁用'}
</span>
</div>
<div class="col-md-9">
<div class="user-info-list">
<div class="user-info-item">
<span class="user-info-label">用户ID:</span>
<span class="user-info-value">#${user.id}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">用户名:</span>
<span class="user-info-value">${user.username}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">昵称:</span>
<span class="user-info-value">${user.nickname || '未设置'}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">邮箱:</span>
<span class="user-info-value">${user.email || '未设置'}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">手机号:</span>
<span class="user-info-value">${user.phone || '未设置'}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">性别:</span>
<span class="user-info-value">${getGenderText(user.gender)}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">生日:</span>
<span class="user-info-value">${user.birthday || '未设置'}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">注册时间:</span>
<span class="user-info-value">${formatDateTime(user.created_at)}</span>
</div>
<div class="user-info-item">
<span class="user-info-label">最后更新:</span>
<span class="user-info-value">${formatDateTime(user.updated_at)}</span>
</div>
</div>
</div>
</div>
</div>
`;
}
// 强制设置模态框中的头像样式
function forceModalAvatarStyles() {
const modalAvatar = document.getElementById('modalAvatar');
if (modalAvatar) {
setAvatarStyles(modalAvatar, '80px');
// 设置容器样式
const wrapper = document.querySelector('.user-avatar-large-wrapper');
if (wrapper) {
wrapper.style.setProperty('width', '80px', 'important');
wrapper.style.setProperty('height', '80px', 'important');
wrapper.style.setProperty('margin', '0 auto', 'important');
wrapper.style.setProperty('overflow', 'hidden', 'important');
wrapper.style.setProperty('border-radius', '50%', 'important');
wrapper.style.setProperty('position', 'relative', 'important');
wrapper.style.setProperty('flex-shrink', '0', 'important');
wrapper.style.setProperty('flex-grow', '0', 'important');
}
}
// 通用的模态框头像处理
const modalAvatars = document.querySelectorAll('.modal .avatar-large');
modalAvatars.forEach(avatar => {
setAvatarStyles(avatar, '80px');
});
}
// 切换用户状态
function toggleUserStatus(userId, currentStatus) {
const action = currentStatus === 1 ? '禁用' : '启用';
const newStatus = currentStatus === 1 ? 0 : 1;
if (!confirm(`确定要${action}此用户吗?`)) {
return;
}
// 显示加载状态
showLoading();
// 发送AJAX请求
fetch(`/admin/users/${userId}/toggle-status`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: newStatus
})
})
.then(response => response.json())
.then(data => {
hideLoading();
if (data.success) {
showSuccess(data.message);
// 刷新页面
setTimeout(() => {
location.reload();
}, 1000);
} else {
showError(data.message);
}
})
.catch(error => {
hideLoading();
console.error('Error:', error);
showError('网络错误,请重试');
});
}
// 获取性别文本
function getGenderText(gender) {
switch (gender) {
case 1: return '男';
case 2: return '女';
default: return '未知';
}
}
// 格式化日期时间
function formatDateTime(dateTimeString) {
if (!dateTimeString) return '未知';
const date = new Date(dateTimeString);
return date.toLocaleString('zh-CN');
}
// 显示成功消息
function showSuccess(message) {
showAlert(message, 'success');
}
// 显示错误消息
function showError(message) {
showAlert(message, 'danger');
}
// 显示提示消息
function showAlert(message, type) {
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type} alert-dismissible fade show`;
alertDiv.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
// 插入到页面顶部
const container = document.querySelector('.admin-content');
container.insertBefore(alertDiv, container.firstChild);
// 3秒后自动关闭
setTimeout(() => {
alertDiv.remove();
}, 3000);
}
// 显示加载状态
function showLoading() {
const loadingDiv = document.createElement('div');
loadingDiv.id = 'loading-overlay';
loadingDiv.innerHTML = `
<div class="loading-spinner">
<i class="bi bi-hourglass-split"></i>
<div>处理中...</div>
</div>
`;
loadingDiv.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
color: white;
`;
document.body.appendChild(loadingDiv);
}
// 隐藏加载状态
function hideLoading() {
const loadingDiv = document.getElementById('loading-overlay');
if (loadingDiv) {
loadingDiv.remove();
}
}
// 页面加载完成后强制设置头像样式
window.addEventListener('load', function() {
forceAvatarStyles();
});
// 定时检查并修复头像样式
setInterval(function() {
// 检查并修复表格头像
const tableAvatars = document.querySelectorAll('.table .user-avatar');
tableAvatars.forEach(avatar => {
if (avatar.offsetWidth > 60 || avatar.offsetHeight > 60) {
setAvatarStyles(avatar, '48px');
}
});
// 检查并修复模态框头像
const modalAvatars = document.querySelectorAll('.modal .avatar-large');
modalAvatars.forEach(avatar => {
if (avatar.offsetWidth > 100 || avatar.offsetHeight > 100) {
setAvatarStyles(avatar, '80px');
}
});
}, 500);