v1.0.10
This commit is contained in:
@@ -0,0 +1,416 @@
|
||||
/**
|
||||
* system.js - 系统管理逻辑(用户管理 / 角色管理 / 操作日志)
|
||||
* 页面:user.html / role.html / log.html
|
||||
*/
|
||||
$(function () {
|
||||
var pageFile = location.pathname.split('/').pop();
|
||||
|
||||
if (pageFile === 'user.html') initUser();
|
||||
else if (pageFile === 'role.html') initRole();
|
||||
else if (pageFile === 'log.html') initLog();
|
||||
else renderShell('权限管理', '系统管理');
|
||||
});
|
||||
|
||||
/* ================= 用户管理 ================= */
|
||||
function initUser() {
|
||||
renderShell('用户管理', '权限管理 / 用户');
|
||||
renderUserPage();
|
||||
initPage('system', function (user) {
|
||||
if (!checkPagePermission('system')) return;
|
||||
loadUsers(1);
|
||||
});
|
||||
|
||||
var currentPage = 1;
|
||||
|
||||
function renderUserPage() {
|
||||
$('#page-content').html(
|
||||
'<div class="card">' +
|
||||
' <div class="toolbar">' +
|
||||
' <input type="text" data-filter="keyword" placeholder="账号/姓名关键词">' +
|
||||
' <select data-filter="role_id" id="filter-role"><option value="">全部角色</option></select>' +
|
||||
' <button class="btn btn-primary" id="btn-search">搜索</button>' +
|
||||
' <button class="btn" id="btn-reset">重置</button>' +
|
||||
' <span class="spacer"></span>' +
|
||||
' <button class="btn btn-success" id="btn-add">+ 新增用户</button>' +
|
||||
' </div>' +
|
||||
' <div class="table-wrap"><table class="grid">' +
|
||||
' <thead><tr><th>ID</th><th>账号</th><th>姓名</th><th>角色</th><th>状态</th><th>最后登录</th><th>登录IP</th><th>创建时间</th><th>操作</th></tr></thead>' +
|
||||
' <tbody id="user-tbody"></tbody>' +
|
||||
' </table></div>' +
|
||||
' <div class="pagination" id="pagination"></div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function loadUsers(page) {
|
||||
currentPage = page;
|
||||
var params = buildFilterParam();
|
||||
params.page = page;
|
||||
params.limit = PAGE_SIZE;
|
||||
|
||||
httpGet('system/user_list.php', params).then(function (data) {
|
||||
var rows = data.list || [];
|
||||
var html = '';
|
||||
rows.forEach(function (r) {
|
||||
html += '<tr>' +
|
||||
'<td>' + r.id + '</td>' +
|
||||
'<td>' + escHtml(r.username) + '</td>' +
|
||||
'<td>' + escHtml(r.real_name || '-') + '</td>' +
|
||||
'<td>' + escHtml(r.role_name || '-') + '</td>' +
|
||||
'<td>' + (r.is_active ? '<span class="tag tag-green">启用</span>' : '<span class="tag tag-red">禁用</span>') + '</td>' +
|
||||
'<td>' + fmtDate(r.last_login_time) + '</td>' +
|
||||
'<td>' + escHtml(r.last_login_ip || '-') + '</td>' +
|
||||
'<td>' + fmtDate(r.created_at) + '</td>' +
|
||||
'<td class="ops">' +
|
||||
' <a onclick="editUser(' + r.id + ')">编辑</a>' +
|
||||
(r.id != 1 ? ' <a class="danger" onclick="delUser(' + r.id + ')">删除</a>' : '') +
|
||||
'</td></tr>';
|
||||
});
|
||||
if (!rows.length) {
|
||||
html = '<tr><td colspan="9" class="empty-tip" style="padding:40px 0;">暂无用户</td></tr>';
|
||||
}
|
||||
$('#user-tbody').html(html);
|
||||
|
||||
// 角色下拉
|
||||
var roles = data.roles || [];
|
||||
var optHtml = '<option value="">全部角色</option>';
|
||||
roles.forEach(function (r) {
|
||||
optHtml += '<option value="' + r.id + '">' + escHtml(r.role_name) + '</option>';
|
||||
});
|
||||
$('#filter-role').html(optHtml);
|
||||
|
||||
renderPagination($('#pagination'), data, loadUsers);
|
||||
});
|
||||
}
|
||||
|
||||
$('#btn-search').on('click', function () { loadUsers(1); });
|
||||
$('#btn-reset').on('click', function () {
|
||||
$('.toolbar [data-filter]').val('');
|
||||
loadUsers(1);
|
||||
});
|
||||
|
||||
$('#btn-add').on('click', function () { openUserForm(null); });
|
||||
|
||||
window.editUser = function (id) {
|
||||
var row = null;
|
||||
$('#user-tbody tr').each(function () {
|
||||
var $tds = $(this).find('td');
|
||||
if ($tds.length && $tds.eq(0).text() == id) {
|
||||
row = {
|
||||
id: id,
|
||||
username: $tds.eq(1).text(),
|
||||
real_name: $tds.eq(2).text() === '-' ? '' : $tds.eq(2).text(),
|
||||
role_name: $tds.eq(3).text(),
|
||||
is_active: $tds.eq(4).find('.tag').hasClass('tag-green') ? 1 : 0
|
||||
};
|
||||
}
|
||||
});
|
||||
openUserForm(row);
|
||||
};
|
||||
|
||||
function openUserForm(user) {
|
||||
var isEdit = !!user;
|
||||
var u = user || {};
|
||||
var roleOptionsHtml = '';
|
||||
$('#filter-role option').each(function () {
|
||||
var $o = $(this);
|
||||
if (!$o.val()) return;
|
||||
roleOptionsHtml += '<option value="' + $o.val() + '"' + (u.role_name === $o.text() ? ' selected' : '') + '>' + escHtml($o.text()) + '</option>';
|
||||
});
|
||||
|
||||
var content =
|
||||
'<form id="user-form" style="padding:18px 22px 4px;">' +
|
||||
'<div class="form-grid">' +
|
||||
' <div class="form-item"><label>登录账号' + (isEdit ? '' : '<span class="req">*</span>') + '</label>' +
|
||||
(isEdit ? '<input type="text" value="' + escHtml(u.username) + '" disabled>' : '<input type="text" name="username" placeholder="3-50位字母/数字/下划线">') + '</div>' +
|
||||
' <div class="form-item"><label>真实姓名</label><input type="text" name="real_name" value="' + escHtml(u.real_name) + '"></div>' +
|
||||
' <div class="form-item"><label>登录密码' + (isEdit ? '(留空不修改)' : '<span class="req">*</span>') + '</label><input type="password" name="password" placeholder="至少6位"></div>' +
|
||||
' <div class="form-item"><label>角色<span class="req">*</span></label><select name="role_id">' + roleOptionsHtml + '</select></div>' +
|
||||
' <div class="form-item"><label>状态</label><select name="is_active">' +
|
||||
' <option value="1"' + (u.is_active !== 0 ? ' selected' : '') + '>启用</option>' +
|
||||
' <option value="0"' + (u.is_active === 0 ? ' selected' : '') + '>禁用</option></select></div>' +
|
||||
'</div>' +
|
||||
'<div class="dialog-footer"><button type="button" class="btn" id="form-cancel">取消</button>' +
|
||||
'<button type="submit" class="btn btn-primary">保存</button></div>' +
|
||||
'</form>';
|
||||
|
||||
var idx = Dialog.open({
|
||||
title: isEdit ? '编辑用户' : '新增用户',
|
||||
area: ['560px', 'auto'],
|
||||
content: content,
|
||||
btn: false
|
||||
});
|
||||
|
||||
$('#form-cancel').on('click', function () { Dialog.close(idx); });
|
||||
|
||||
$('#user-form').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var data = {};
|
||||
$(this).find('input, select').each(function () {
|
||||
var name = $(this).attr('name');
|
||||
if (!name) return;
|
||||
data[name] = $(this).val();
|
||||
});
|
||||
if (isEdit) data.id = u.id;
|
||||
|
||||
httpPost(isEdit ? 'system/user_update.php' : 'system/user_add.php', data).then(function () {
|
||||
Dialog.success('保存成功', function () {
|
||||
Dialog.close(idx);
|
||||
loadUsers(currentPage);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.delUser = function (id) {
|
||||
Dialog.confirm('确定删除该用户吗?', function () {
|
||||
httpPost('system/user_delete.php', { id: id }).then(function () {
|
||||
Dialog.success('删除成功', function () { loadUsers(currentPage); });
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/* ================= 角色管理 ================= */
|
||||
function initRole() {
|
||||
renderShell('角色管理', '权限管理 / 角色');
|
||||
renderRolePage();
|
||||
initPage('system', function (user) {
|
||||
if (!checkPagePermission('system')) return;
|
||||
loadRoles(1);
|
||||
});
|
||||
|
||||
var currentPage = 1;
|
||||
|
||||
function renderRolePage() {
|
||||
$('#page-content').html(
|
||||
'<div class="card">' +
|
||||
' <div class="toolbar">' +
|
||||
' <input type="text" data-filter="keyword" placeholder="角色名称关键词">' +
|
||||
' <button class="btn btn-primary" id="btn-search">搜索</button>' +
|
||||
' <button class="btn" id="btn-reset">重置</button>' +
|
||||
' <span class="spacer"></span>' +
|
||||
' <button class="btn btn-success" id="btn-add">+ 新增角色</button>' +
|
||||
' </div>' +
|
||||
' <div class="table-wrap"><table class="grid">' +
|
||||
' <thead><tr><th>ID</th><th>角色名称</th><th>权限</th><th>用户数</th><th>状态</th><th>创建时间</th><th>操作</th></tr></thead>' +
|
||||
' <tbody id="role-tbody"></tbody>' +
|
||||
' </table></div>' +
|
||||
' <div class="pagination" id="pagination"></div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function loadRoles(page) {
|
||||
currentPage = page;
|
||||
var params = buildFilterParam();
|
||||
params.page = page;
|
||||
params.limit = PAGE_SIZE;
|
||||
|
||||
httpGet('system/role_list.php', params).then(function (data) {
|
||||
var rows = data.list || [];
|
||||
var html = '';
|
||||
rows.forEach(function (r) {
|
||||
var permTags = (r.permissions || []).map(function (p) {
|
||||
var m = MENU_MAP[p];
|
||||
return '<span class="tag" style="margin:2px 4px 2px 0;">' + (m ? escHtml(m.name) : escHtml(p)) + '</span>';
|
||||
}).join('');
|
||||
html += '<tr>' +
|
||||
'<td>' + r.id + '</td>' +
|
||||
'<td>' + escHtml(r.role_name) + '</td>' +
|
||||
'<td>' + (permTags || '<span class="tag tag-gray">无权限</span>') + '</td>' +
|
||||
'<td>' + r.user_count + '</td>' +
|
||||
'<td>' + (r.is_active ? '<span class="tag tag-green">启用</span>' : '<span class="tag tag-red">禁用</span>') + '</td>' +
|
||||
'<td>' + fmtDate(r.created_at) + '</td>' +
|
||||
'<td class="ops">' +
|
||||
(r.id != 1 ? ' <a onclick="editRole(' + r.id + ')">编辑</a>' : '') +
|
||||
(r.id != 1 ? ' <a class="danger" onclick="delRole(' + r.id + ')">删除</a>' : '<span style="color:#b6bfcc;">内置</span>') +
|
||||
'</td></tr>';
|
||||
});
|
||||
if (!rows.length) {
|
||||
html = '<tr><td colspan="7" class="empty-tip" style="padding:40px 0;">暂无角色</td></tr>';
|
||||
}
|
||||
$('#role-tbody').html(html);
|
||||
renderPagination($('#pagination'), data, loadRoles);
|
||||
});
|
||||
}
|
||||
|
||||
$('#btn-search').on('click', function () { loadRoles(1); });
|
||||
$('#btn-reset').on('click', function () {
|
||||
$('.toolbar [data-filter]').val('');
|
||||
loadRoles(1);
|
||||
});
|
||||
|
||||
$('#btn-add').on('click', function () { openRoleForm(null); });
|
||||
|
||||
window.editRole = function (id) {
|
||||
var row = null;
|
||||
$('#role-tbody tr').each(function () {
|
||||
var $tds = $(this).find('td');
|
||||
if ($tds.length && $tds.eq(0).text() == id) {
|
||||
var perms = [];
|
||||
$tds.eq(2).find('.tag').each(function () { perms.push($(this).text()); });
|
||||
row = {
|
||||
id: id,
|
||||
role_name: $tds.eq(1).text(),
|
||||
permissions: perms,
|
||||
is_active: $tds.eq(4).find('.tag').hasClass('tag-green') ? 1 : 0
|
||||
};
|
||||
}
|
||||
});
|
||||
openRoleForm(row);
|
||||
};
|
||||
|
||||
function openRoleForm(role) {
|
||||
var isEdit = !!role;
|
||||
var r = role || {};
|
||||
var permHtml = '';
|
||||
PERMISSION_OPTIONS.forEach(function (p) {
|
||||
var checked = (r.permissions || []).indexOf(p.key) >= 0 ? 'checked' : '';
|
||||
permHtml += '<label style="display:inline-block;min-width:110px;margin:4px 8px 4px 0;font-size:13px;">' +
|
||||
'<input type="checkbox" name="perm" value="' + p.key + '" ' + checked + '> ' + p.name + '</label>';
|
||||
});
|
||||
|
||||
var content =
|
||||
'<form id="role-form" style="padding:18px 22px 4px;">' +
|
||||
'<div class="form-grid">' +
|
||||
' <div class="form-item"><label>角色名称<span class="req">*</span></label><input type="text" name="role_name" value="' + escHtml(r.role_name) + '"></div>' +
|
||||
' <div class="form-item"><label>状态</label><select name="is_active">' +
|
||||
' <option value="1"' + (r.is_active !== 0 ? ' selected' : '') + '>启用</option>' +
|
||||
' <option value="0"' + (r.is_active === 0 ? ' selected' : '') + '>禁用</option></select></div>' +
|
||||
' <div class="form-item full"><label>权限分配</label><div style="border:1px solid #eef0f4;border-radius:4px;padding:10px;background:#fafbfd;">' + permHtml + '</div></div>' +
|
||||
'</div>' +
|
||||
'<div class="dialog-footer"><button type="button" class="btn" id="form-cancel">取消</button>' +
|
||||
'<button type="submit" class="btn btn-primary">保存</button></div>' +
|
||||
'</form>';
|
||||
|
||||
var idx = Dialog.open({
|
||||
title: isEdit ? '编辑角色' : '新增角色',
|
||||
area: ['620px', 'auto'],
|
||||
content: content,
|
||||
btn: false
|
||||
});
|
||||
|
||||
$('#form-cancel').on('click', function () { Dialog.close(idx); });
|
||||
|
||||
$('#role-form').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var perms = [];
|
||||
$('input[name="perm"]:checked').each(function () { perms.push($(this).val()); });
|
||||
var data = {
|
||||
role_name: $('input[name="role_name"]').val(),
|
||||
is_active: $('select[name="is_active"]').val(),
|
||||
permissions: JSON.stringify(perms)
|
||||
};
|
||||
if (isEdit) data.id = r.id;
|
||||
|
||||
httpPost(isEdit ? 'system/role_update.php' : 'system/role_add.php', data).then(function () {
|
||||
Dialog.success('保存成功', function () {
|
||||
Dialog.close(idx);
|
||||
loadRoles(currentPage);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.delRole = function (id) {
|
||||
Dialog.confirm('确定删除该角色吗?', function () {
|
||||
httpPost('system/role_delete.php', { id: id }).then(function () {
|
||||
Dialog.success('删除成功', function () { loadRoles(currentPage); });
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/* ================= 操作日志 ================= */
|
||||
function initLog() {
|
||||
renderShell('操作日志', '权限管理 / 操作日志(仅超级管理员)');
|
||||
renderLogPage();
|
||||
initPage('log', function (user) {
|
||||
var perms = user.permissions || [];
|
||||
if (perms.indexOf('log') < 0) {
|
||||
Dialog.alert('仅超级管理员可查看操作日志', function () {
|
||||
location.href = 'dashboard.html';
|
||||
});
|
||||
return;
|
||||
}
|
||||
loadLogs(1);
|
||||
});
|
||||
|
||||
var currentPage = 1;
|
||||
|
||||
function renderLogPage() {
|
||||
$('#page-content').html(
|
||||
'<div class="card">' +
|
||||
' <div class="toolbar">' +
|
||||
' <input type="text" data-filter="keyword" placeholder="账号/内容/模块关键词">' +
|
||||
' <select data-filter="action" id="filter-action"><option value="">全部操作</option></select>' +
|
||||
' <select data-filter="module" id="filter-module"><option value="">全部模块</option></select>' +
|
||||
' <input type="text" data-filter="username" placeholder="操作人账号">' +
|
||||
' <input type="date" data-filter="start_date" title="开始日期">' +
|
||||
' <input type="date" data-filter="end_date" title="结束日期">' +
|
||||
' <button class="btn btn-primary" id="btn-search">搜索</button>' +
|
||||
' <button class="btn" id="btn-reset">重置</button>' +
|
||||
' </div>' +
|
||||
' <div class="table-wrap"><table class="grid">' +
|
||||
' <thead><tr><th>ID</th><th>账号</th><th>操作</th><th>模块</th><th>对象表</th><th>对象ID</th><th>内容</th><th>IP</th><th>时间</th></tr></thead>' +
|
||||
' <tbody id="log-tbody"></tbody>' +
|
||||
' </table></div>' +
|
||||
' <div class="pagination" id="pagination"></div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function loadLogs(page) {
|
||||
currentPage = page;
|
||||
var params = buildFilterParam();
|
||||
params.page = page;
|
||||
params.limit = PAGE_SIZE;
|
||||
|
||||
httpGet('system/log_list.php', params).then(function (data) {
|
||||
var rows = data.list || [];
|
||||
var html = '';
|
||||
rows.forEach(function (r) {
|
||||
var content = '';
|
||||
try {
|
||||
var obj = JSON.parse(r.content || 'null');
|
||||
content = obj ? JSON.stringify(obj) : '';
|
||||
} catch (e) {}
|
||||
html += '<tr>' +
|
||||
'<td>' + r.id + '</td>' +
|
||||
'<td>' + escHtml(r.username) + '</td>' +
|
||||
'<td><span class="tag">' + escHtml(r.action) + '</span></td>' +
|
||||
'<td>' + escHtml(r.module) + '</td>' +
|
||||
'<td>' + escHtml(r.target_table || '-') + '</td>' +
|
||||
'<td>' + (r.target_id || '-') + '</td>' +
|
||||
'<td title="' + escHtml(content) + '">' + escHtml((content || '-').substring(0, 30)) + '</td>' +
|
||||
'<td>' + escHtml(r.ip || '-') + '</td>' +
|
||||
'<td>' + fmtDate(r.created_at) + '</td></tr>';
|
||||
});
|
||||
if (!rows.length) {
|
||||
html = '<tr><td colspan="9" class="empty-tip" style="padding:40px 0;">近1个月暂无操作日志</td></tr>';
|
||||
}
|
||||
$('#log-tbody').html(html);
|
||||
renderPagination($('#pagination'), data, loadLogs);
|
||||
|
||||
// 筛选下拉
|
||||
var dict = data.dict || {};
|
||||
if (dict.actions && dict.actions.length) {
|
||||
var h = '<option value="">全部操作</option>';
|
||||
dict.actions.forEach(function (a) { h += '<option value="' + escHtml(a) + '">' + escHtml(a) + '</option>'; });
|
||||
$('#filter-action').html(h);
|
||||
}
|
||||
if (dict.modules && dict.modules.length) {
|
||||
var h2 = '<option value="">全部模块</option>';
|
||||
dict.modules.forEach(function (m) { h2 += '<option value="' + escHtml(m) + '">' + escHtml(m) + '</option>'; });
|
||||
$('#filter-module').html(h2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#btn-search').on('click', function () { loadLogs(1); });
|
||||
$('#btn-reset').on('click', function () {
|
||||
$('.toolbar [data-filter]').val('');
|
||||
loadLogs(1);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user