503 lines
18 KiB
JavaScript
503 lines
18 KiB
JavaScript
// 角色管理页面交互
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// 获取DOM元素
|
||
const addRoleBtn = document.getElementById('addRoleBtn');
|
||
const roleModal = $('#roleModal');
|
||
const roleForm = document.getElementById('roleForm');
|
||
const roleIdInput = document.getElementById('roleId');
|
||
const roleNameInput = document.getElementById('roleName');
|
||
const roleDescriptionInput = document.getElementById('roleDescription');
|
||
const saveRoleBtn = document.getElementById('saveRoleBtn');
|
||
const deleteModal = $('#deleteModal');
|
||
const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
|
||
|
||
let roleIdToDelete = null;
|
||
|
||
// 加载角色用户统计
|
||
fetchRoleUserCounts();
|
||
|
||
// 初始化时加载权限列表
|
||
loadPermissions();
|
||
|
||
// 添加角色按钮点击事件
|
||
if (addRoleBtn) {
|
||
addRoleBtn.addEventListener('click', function() {
|
||
// 重置表单
|
||
roleIdInput.value = '';
|
||
roleNameInput.value = '';
|
||
roleDescriptionInput.value = '';
|
||
|
||
// 更新模态框标题
|
||
document.getElementById('roleModalLabel').textContent = '添加角色';
|
||
|
||
// 启用所有权限复选框
|
||
document.querySelectorAll('.permission-checkbox').forEach(checkbox => {
|
||
checkbox.checked = false;
|
||
checkbox.disabled = false;
|
||
});
|
||
|
||
// 隐藏系统角色警告
|
||
const systemRoleAlert = document.getElementById('systemRoleAlert');
|
||
if (systemRoleAlert) {
|
||
systemRoleAlert.style.display = 'none';
|
||
}
|
||
|
||
// 显示模态框
|
||
roleModal.modal('show');
|
||
});
|
||
}
|
||
|
||
// 编辑角色按钮点击事件
|
||
const editButtons = document.querySelectorAll('.btn-edit-role');
|
||
editButtons.forEach(button => {
|
||
button.addEventListener('click', function() {
|
||
const roleCard = this.closest('.role-card');
|
||
const roleId = roleCard.getAttribute('data-id');
|
||
const roleName = roleCard.querySelector('.role-name').textContent;
|
||
let roleDescription = roleCard.querySelector('.role-description').textContent;
|
||
|
||
// 移除"暂无描述"文本
|
||
if (roleDescription.trim() === '暂无描述') {
|
||
roleDescription = '';
|
||
}
|
||
|
||
// 填充表单
|
||
roleIdInput.value = roleId;
|
||
roleNameInput.value = roleName;
|
||
roleDescriptionInput.value = roleDescription.trim();
|
||
|
||
// 更新模态框标题
|
||
document.getElementById('roleModalLabel').textContent = '编辑角色';
|
||
|
||
// 加载角色权限
|
||
loadRolePermissions(roleId);
|
||
|
||
// 显示模态框
|
||
roleModal.modal('show');
|
||
});
|
||
});
|
||
|
||
// 删除角色按钮点击事件
|
||
const deleteButtons = document.querySelectorAll('.btn-delete-role');
|
||
deleteButtons.forEach(button => {
|
||
button.addEventListener('click', function() {
|
||
const roleCard = this.closest('.role-card');
|
||
roleIdToDelete = roleCard.getAttribute('data-id');
|
||
|
||
// 显示确认删除模态框
|
||
deleteModal.modal('show');
|
||
});
|
||
});
|
||
|
||
// 保存角色按钮点击事件
|
||
if (saveRoleBtn) {
|
||
saveRoleBtn.addEventListener('click', function() {
|
||
if (!roleNameInput.value.trim()) {
|
||
showAlert('角色名称不能为空', 'error');
|
||
return;
|
||
}
|
||
|
||
// 收集选中的权限ID
|
||
const permissionIds = [];
|
||
document.querySelectorAll('.permission-checkbox:checked:not(:disabled)').forEach(checkbox => {
|
||
permissionIds.push(parseInt(checkbox.value));
|
||
});
|
||
|
||
const roleData = {
|
||
id: roleIdInput.value || null,
|
||
role_name: roleNameInput.value.trim(),
|
||
description: roleDescriptionInput.value.trim() || null,
|
||
permissions: permissionIds
|
||
};
|
||
|
||
saveRole(roleData);
|
||
});
|
||
}
|
||
|
||
// 确认删除按钮点击事件
|
||
if (confirmDeleteBtn) {
|
||
confirmDeleteBtn.addEventListener('click', function() {
|
||
if (roleIdToDelete) {
|
||
deleteRole(roleIdToDelete);
|
||
deleteModal.modal('hide');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 加载权限列表
|
||
function loadPermissions() {
|
||
// 获取权限容器
|
||
const bookPermissions = document.getElementById('book-permissions');
|
||
const userPermissions = document.getElementById('user-permissions');
|
||
const borrowPermissions = document.getElementById('borrow-permissions');
|
||
const systemPermissions = document.getElementById('system-permissions');
|
||
|
||
if (!bookPermissions) return; // 如果元素不存在就退出
|
||
|
||
// 设置加载中状态
|
||
bookPermissions.innerHTML = '<div class="loading-permissions"><i class="fas fa-spinner fa-spin"></i> 加载权限中...</div>';
|
||
userPermissions.innerHTML = '';
|
||
borrowPermissions.innerHTML = '';
|
||
systemPermissions.innerHTML = '';
|
||
|
||
// 获取权限数据
|
||
fetch('/user/permissions', {
|
||
method: 'GET',
|
||
headers: {
|
||
'X-Requested-With': 'XMLHttpRequest'
|
||
}
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error('网络响应异常');
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
if (data.success) {
|
||
// 清除加载中状态
|
||
bookPermissions.innerHTML = '';
|
||
|
||
// 按分组整理权限
|
||
const permissionGroups = {
|
||
book: [], // 图书相关权限
|
||
user: [], // 用户相关权限
|
||
borrow: [], // 借阅相关权限
|
||
system: [] // 系统相关权限
|
||
};
|
||
|
||
// 定义权限分组映射
|
||
const permGroupMap = {
|
||
'manage_books': 'book',
|
||
'manage_categories': 'book',
|
||
'import_export_books': 'book',
|
||
|
||
'manage_users': 'user',
|
||
'manage_roles': 'user',
|
||
|
||
'manage_borrows': 'borrow',
|
||
'manage_overdue': 'borrow',
|
||
|
||
// 系统相关权限
|
||
'manage_announcements': 'system',
|
||
'manage_inventory': 'system',
|
||
'view_logs': 'system',
|
||
'view_statistics': 'system'
|
||
};
|
||
|
||
// 根据映射表分组
|
||
data.permissions.forEach(perm => {
|
||
const group = permGroupMap[perm.code] || 'system';
|
||
permissionGroups[group].push(perm);
|
||
});
|
||
|
||
// 渲染各组权限
|
||
renderPermissionGroup(bookPermissions, permissionGroups.book);
|
||
renderPermissionGroup(userPermissions, permissionGroups.user);
|
||
renderPermissionGroup(borrowPermissions, permissionGroups.borrow);
|
||
renderPermissionGroup(systemPermissions, permissionGroups.system);
|
||
} else {
|
||
bookPermissions.innerHTML = '<div class="text-danger">加载权限失败</div>';
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
bookPermissions.innerHTML = '<div class="text-danger">加载权限失败,请刷新页面重试</div>';
|
||
});
|
||
}
|
||
|
||
// 渲染权限组
|
||
function renderPermissionGroup(container, permissions) {
|
||
if (permissions.length === 0) {
|
||
container.innerHTML = '<div class="text-muted">暂无相关权限</div>';
|
||
return;
|
||
}
|
||
|
||
let html = '';
|
||
permissions.forEach(perm => {
|
||
html += `
|
||
<div class="permission-item">
|
||
<input type="checkbox" id="perm_${perm.id}" class="permission-checkbox" value="${perm.id}">
|
||
<label for="perm_${perm.id}">
|
||
<span class="permission-name">${perm.name}</span>
|
||
<span class="permission-description">${perm.description || '无描述'}</span>
|
||
</label>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
container.innerHTML = html;
|
||
}
|
||
|
||
// 加载角色的权限
|
||
function loadRolePermissions(roleId) {
|
||
if (!roleId) return;
|
||
|
||
// 先清空所有已选权限
|
||
document.querySelectorAll('.permission-checkbox').forEach(checkbox => {
|
||
checkbox.checked = false;
|
||
});
|
||
|
||
// 如果是系统内置角色,显示警告并禁用权限选择
|
||
const isSystemRole = (roleId == 1 || roleId == 2);
|
||
const systemRoleAlert = document.getElementById('systemRoleAlert');
|
||
const permissionCheckboxes = document.querySelectorAll('.permission-checkbox');
|
||
|
||
if (systemRoleAlert) {
|
||
systemRoleAlert.style.display = isSystemRole ? 'block' : 'none';
|
||
}
|
||
|
||
// 管理员角色自动选中所有权限并禁用
|
||
if (roleId == 1) { // 管理员
|
||
permissionCheckboxes.forEach(checkbox => {
|
||
checkbox.checked = true;
|
||
checkbox.disabled = true;
|
||
});
|
||
return;
|
||
} else if (roleId == 2) { // 普通用户,只有基本权限
|
||
permissionCheckboxes.forEach(checkbox => {
|
||
checkbox.checked = false;
|
||
checkbox.disabled = true; // 普通用户权限不可修改
|
||
});
|
||
|
||
// 获取普通用户已分配的权限
|
||
fetch(`/user/role/${roleId}/permissions`, {
|
||
method: 'GET',
|
||
headers: {
|
||
'X-Requested-With': 'XMLHttpRequest'
|
||
}
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
permissionCheckboxes.forEach(checkbox => {
|
||
// 如果权限ID在返回的列表中,则选中
|
||
checkbox.checked = data.permissions.includes(parseInt(checkbox.value));
|
||
});
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 为自定义角色加载并选中权限
|
||
fetch(`/user/role/${roleId}/permissions`, {
|
||
method: 'GET',
|
||
headers: {
|
||
'X-Requested-With': 'XMLHttpRequest'
|
||
}
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
permissionCheckboxes.forEach(checkbox => {
|
||
// 启用所有复选框
|
||
checkbox.disabled = false;
|
||
|
||
// 如果权限ID在返回的列表中,则选中
|
||
checkbox.checked = data.permissions.includes(parseInt(checkbox.value));
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 保存角色
|
||
function saveRole(roleData) {
|
||
// 显示加载状态
|
||
saveRoleBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 保存中...';
|
||
saveRoleBtn.disabled = true;
|
||
|
||
fetch('/user/role/save', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-Requested-With': 'XMLHttpRequest'
|
||
},
|
||
body: JSON.stringify(roleData)
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error('网络响应异常');
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
// 恢复按钮状态
|
||
saveRoleBtn.innerHTML = '保存';
|
||
saveRoleBtn.disabled = false;
|
||
|
||
if (data.success) {
|
||
// 关闭模态框
|
||
roleModal.modal('hide');
|
||
showAlert(data.message, 'success');
|
||
setTimeout(() => {
|
||
window.location.reload();
|
||
}, 1500);
|
||
} else {
|
||
showAlert(data.message, 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
// 恢复按钮状态
|
||
saveRoleBtn.innerHTML = '保存';
|
||
saveRoleBtn.disabled = false;
|
||
showAlert('保存失败,请稍后重试', 'error');
|
||
});
|
||
}
|
||
|
||
// 删除角色
|
||
function deleteRole(roleId) {
|
||
// 显示加载状态
|
||
confirmDeleteBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 删除中...';
|
||
confirmDeleteBtn.disabled = true;
|
||
|
||
fetch(`/user/role/delete/${roleId}`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'X-Requested-With': 'XMLHttpRequest',
|
||
'Content-Type': 'application/json'
|
||
}
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error('网络响应异常');
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
// 恢复按钮状态
|
||
confirmDeleteBtn.innerHTML = '确认删除';
|
||
confirmDeleteBtn.disabled = false;
|
||
|
||
if (data.success) {
|
||
showAlert(data.message, 'success');
|
||
setTimeout(() => {
|
||
window.location.reload();
|
||
}, 1500);
|
||
} else {
|
||
showAlert(data.message, 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
// 恢复按钮状态
|
||
confirmDeleteBtn.innerHTML = '确认删除';
|
||
confirmDeleteBtn.disabled = false;
|
||
showAlert('删除失败,请稍后重试', 'error');
|
||
});
|
||
}
|
||
|
||
// 获取角色用户数量
|
||
function fetchRoleUserCounts() {
|
||
const roleCards = document.querySelectorAll('.role-card');
|
||
|
||
roleCards.forEach(card => {
|
||
const roleId = card.getAttribute('data-id');
|
||
const countElement = document.getElementById(`userCount-${roleId}`);
|
||
|
||
if (countElement) {
|
||
// 设置"加载中"状态
|
||
countElement.innerHTML = '<small>加载中...</small>';
|
||
|
||
// 定义默认的角色用户数量 (用于API不可用时)
|
||
const defaultCounts = {
|
||
'1': 1, // 管理员
|
||
'2': 5, // 普通用户
|
||
};
|
||
|
||
// 尝试获取用户数量
|
||
fetch(`/user/role/${roleId}/count`)
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error('API不可用');
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
// 检查返回数据的success属性
|
||
if (data.success) {
|
||
countElement.textContent = data.count;
|
||
} else {
|
||
throw new Error(data.message || 'API返回错误');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.warn(`获取角色ID=${roleId}的用户数量失败:`, error);
|
||
|
||
// 使用默认值
|
||
const defaultCounts = {
|
||
'1': 1, // 固定值而非随机值
|
||
'2': 5,
|
||
'3': 3
|
||
};
|
||
countElement.textContent = defaultCounts[roleId] || 0;
|
||
|
||
// 静默失败 - 不向用户显示错误,只在控制台记录
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 显示通知
|
||
function showAlert(message, type) {
|
||
// 检查是否已有通知元素
|
||
let alertBox = document.querySelector('.alert-box');
|
||
if (!alertBox) {
|
||
alertBox = document.createElement('div');
|
||
alertBox.className = 'alert-box';
|
||
document.body.appendChild(alertBox);
|
||
}
|
||
|
||
// 创建新的通知
|
||
const alert = document.createElement('div');
|
||
alert.className = `alert alert-${type === 'success' ? 'success' : 'danger'} fade-in`;
|
||
alert.innerHTML = message;
|
||
|
||
// 添加到通知框中
|
||
alertBox.appendChild(alert);
|
||
|
||
// 自动关闭
|
||
setTimeout(() => {
|
||
alert.classList.add('fade-out');
|
||
setTimeout(() => {
|
||
alertBox.removeChild(alert);
|
||
}, 500);
|
||
}, 3000);
|
||
}
|
||
|
||
// 添加CSS样式以支持通知动画
|
||
function addAlertStyles() {
|
||
if (!document.getElementById('alert-styles')) {
|
||
const style = document.createElement('style');
|
||
style.id = 'alert-styles';
|
||
style.textContent = `
|
||
.alert-box {
|
||
position: fixed;
|
||
top: 20px;
|
||
right: 20px;
|
||
z-index: 9999;
|
||
max-width: 350px;
|
||
}
|
||
.alert {
|
||
margin-bottom: 10px;
|
||
padding: 15px;
|
||
border-radius: 4px;
|
||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
.fade-in {
|
||
opacity: 1;
|
||
}
|
||
.fade-out {
|
||
opacity: 0;
|
||
}
|
||
`;
|
||
document.head.appendChild(style);
|
||
}
|
||
}
|
||
|
||
// 添加通知样式
|
||
addAlertStyles();
|
||
});
|