(function () {
|
var config = Object.assign({
|
apiBaseUrl: "http://localhost:9098"
|
}, window.VISITOR_LOGIN_CONFIG || {});
|
|
var params = new URLSearchParams(window.location.search);
|
var state = {
|
mode: params.get("mode") || "add",
|
roleId: Number(params.get("roleId") || 0),
|
permissionTree: [],
|
checkedMenuIds: [],
|
nodeMap: {}
|
};
|
|
init();
|
|
function init() {
|
if (!getToken()) {
|
redirectToLogin();
|
return;
|
}
|
bindLayoutActions();
|
bindPageActions();
|
applyUserInfo(readLoginUser());
|
loadProfileName();
|
applyMode();
|
loadPermissionTree().then(function () {
|
if (state.mode === "edit" || state.mode === "detail") {
|
loadRoleDetail();
|
} else {
|
renderPermissionTable();
|
}
|
});
|
}
|
|
function bindLayoutActions() {
|
var userMenuButton = document.getElementById("userMenuButton");
|
var userDropdown = document.getElementById("userDropdown");
|
var fullscreenButton = document.querySelector(".icon-button");
|
|
userMenuButton.addEventListener("click", function (event) {
|
event.stopPropagation();
|
var hidden = userDropdown.hidden;
|
userDropdown.hidden = !hidden;
|
userMenuButton.setAttribute("aria-expanded", String(hidden));
|
});
|
|
userDropdown.addEventListener("click", function (event) {
|
var action = event.target.getAttribute("data-action");
|
if (!action) {
|
return;
|
}
|
userDropdown.hidden = true;
|
userMenuButton.setAttribute("aria-expanded", "false");
|
if (action === "home") {
|
window.location.href = "./dashboard.html";
|
} else if (action === "logout") {
|
logout();
|
}
|
});
|
|
document.addEventListener("click", function () {
|
userDropdown.hidden = true;
|
userMenuButton.setAttribute("aria-expanded", "false");
|
});
|
|
fullscreenButton.addEventListener("click", function () {
|
if (!document.fullscreenElement && document.documentElement.requestFullscreen) {
|
document.documentElement.requestFullscreen();
|
} else if (document.exitFullscreen) {
|
document.exitFullscreen();
|
}
|
});
|
}
|
|
function bindPageActions() {
|
document.getElementById("backButton").addEventListener("click", goBack);
|
document.getElementById("cancelButton").addEventListener("click", goBack);
|
document.getElementById("roleForm").addEventListener("submit", function (event) {
|
event.preventDefault();
|
saveRole();
|
});
|
}
|
|
function applyMode() {
|
var title = "新增角色";
|
if (state.mode === "edit") {
|
title = "编辑角色";
|
} else if (state.mode === "detail") {
|
title = "角色详情";
|
}
|
document.title = title + " - 访客机自助登记管理平台";
|
document.getElementById("pageTitle").textContent = title;
|
document.getElementById("pageTab").textContent = title;
|
document.getElementById("formActions").hidden = state.mode === "detail";
|
document.getElementById("detailPermissionTab").hidden = state.mode !== "detail";
|
setReadonly(state.mode === "detail");
|
}
|
|
function setReadonly(readonly) {
|
document.getElementById("roleName").disabled = readonly;
|
document.getElementById("roleRemark").disabled = readonly;
|
}
|
|
function loadProfileName() {
|
apiRequest("/system/user/profile", { method: "GET" }).then(function (result) {
|
applyUserInfo(result.data || {});
|
}).catch(function () {
|
applyUserInfo(readLoginUser());
|
});
|
}
|
|
function loadPermissionTree() {
|
return apiRequest("/system/role/manage/permissionTree", {
|
method: "POST",
|
body: JSON.stringify({})
|
}).then(function (result) {
|
state.permissionTree = Array.isArray(result.data) ? result.data : [];
|
buildNodeMap(state.permissionTree);
|
}).catch(function () {
|
state.permissionTree = [];
|
state.nodeMap = {};
|
});
|
}
|
|
function loadRoleDetail() {
|
if (!state.roleId) {
|
AppMessage.error("操作失败:角色ID不能为空");
|
return;
|
}
|
apiRequest("/system/role/manage/detail", {
|
method: "POST",
|
body: JSON.stringify({ roleId: state.roleId })
|
}).then(function (result) {
|
var data = result.data || {};
|
document.getElementById("roleName").value = data.roleName || "";
|
document.getElementById("roleRemark").value = data.remark || "";
|
state.checkedMenuIds = Array.isArray(data.menuIds) ? data.menuIds.map(Number) : [];
|
renderPermissionTable();
|
}).catch(function (error) {
|
AppMessage.error("操作失败:" + (error.message || "角色详情加载失败"));
|
renderPermissionTable();
|
});
|
}
|
|
function renderPermissionTable() {
|
var body = document.getElementById("permissionTableBody");
|
var empty = document.getElementById("permissionEmpty");
|
var rows = buildPermissionRows(state.permissionTree);
|
empty.hidden = rows.length > 0;
|
body.innerHTML = rows.map(function (row, index) {
|
var moduleCell = "";
|
if (row.moduleFirst) {
|
moduleCell = '<td rowspan="' + row.moduleRowspan + '">' + renderCheck(row.module) + "</td>";
|
}
|
return [
|
"<tr>",
|
moduleCell,
|
"<td>" + renderCheck(row.page) + "</td>",
|
"<td>" + row.actions.map(renderCheck).join("") + "</td>",
|
"</tr>"
|
].join("");
|
}).join("");
|
|
body.querySelectorAll("input[type='checkbox']").forEach(function (input) {
|
input.addEventListener("change", function () {
|
syncRelatedChecks(input);
|
});
|
});
|
}
|
|
function buildPermissionRows(tree) {
|
var rows = [];
|
tree.forEach(function (module) {
|
var pageRows = buildModuleRows(module);
|
pageRows.forEach(function (row, index) {
|
row.moduleFirst = index === 0;
|
row.moduleRowspan = pageRows.length;
|
rows.push(row);
|
});
|
});
|
return rows;
|
}
|
|
function buildModuleRows(module) {
|
var children = Array.isArray(module.children) ? module.children : [];
|
var pages = children.filter(function (child) {
|
return child.menuType !== "F";
|
});
|
if (!pages.length) {
|
pages = [module];
|
}
|
return pages.map(function (page) {
|
var actionChildren = (page.children || []).filter(function (child) {
|
return child.menuType === "F";
|
});
|
var actions = actionChildren.length ? actionChildren : [page];
|
return {
|
module: toCheckItem(module),
|
page: toCheckItem(page),
|
actions: actions.map(toCheckItem)
|
};
|
});
|
}
|
|
function renderCheck(item) {
|
var checked = item.id && state.checkedMenuIds.indexOf(Number(item.id)) > -1;
|
var disabled = state.mode === "detail" || !item.id;
|
return [
|
'<label class="permission-check">',
|
'<input type="checkbox" value="' + (item.id || "") + '" data-parent-id="' + (item.parentId || "") + '"' + (checked ? " checked" : "") + (disabled ? " disabled" : "") + ">",
|
"<span>" + escapeHtml(item.name || "-") + "</span>",
|
"</label>"
|
].join("");
|
}
|
|
function toCheckItem(node) {
|
return {
|
id: node && node.menuId ? Number(node.menuId) : null,
|
parentId: node && node.parentId ? Number(node.parentId) : null,
|
name: node && node.menuName ? node.menuName : "-"
|
};
|
}
|
|
function syncRelatedChecks(input) {
|
var id = Number(input.value || 0);
|
if (!id) {
|
return;
|
}
|
document.querySelectorAll('input[value="' + id + '"]').forEach(function (sameInput) {
|
sameInput.checked = input.checked;
|
});
|
if (input.checked) {
|
checkParents(id);
|
return;
|
}
|
uncheckChildren(id);
|
}
|
|
function checkParents(id) {
|
var node = state.nodeMap[id];
|
while (node && node.parentId) {
|
document.querySelectorAll('input[value="' + node.parentId + '"]').forEach(function (parentInput) {
|
parentInput.checked = true;
|
});
|
node = state.nodeMap[node.parentId];
|
}
|
}
|
|
function uncheckChildren(id) {
|
Object.keys(state.nodeMap).forEach(function (key) {
|
var node = state.nodeMap[key];
|
if (isDescendant(Number(key), id)) {
|
document.querySelectorAll('input[value="' + key + '"]').forEach(function (item) {
|
item.checked = false;
|
});
|
}
|
});
|
}
|
|
function isDescendant(childId, parentId) {
|
var node = state.nodeMap[childId];
|
while (node && node.parentId) {
|
if (Number(node.parentId) === Number(parentId)) {
|
return true;
|
}
|
node = state.nodeMap[node.parentId];
|
}
|
return false;
|
}
|
|
function buildNodeMap(tree) {
|
state.nodeMap = {};
|
walkNodes(tree, null);
|
}
|
|
function walkNodes(nodes, parentId) {
|
(nodes || []).forEach(function (node) {
|
var menuId = Number(node.menuId || 0);
|
if (!node.parentId && parentId) {
|
node.parentId = parentId;
|
}
|
if (menuId) {
|
state.nodeMap[menuId] = node;
|
}
|
walkNodes(node.children || [], menuId);
|
});
|
}
|
|
function saveRole() {
|
if (state.mode === "detail") {
|
return;
|
}
|
var roleName = document.getElementById("roleName").value.trim();
|
if (!roleName) {
|
AppMessage.error("操作失败:请输入角色名称");
|
return;
|
}
|
var payload = {
|
roleName: roleName,
|
remark: document.getElementById("roleRemark").value.trim(),
|
menuIds: getCheckedMenuIds()
|
};
|
var path = "/system/role/manage/add";
|
if (state.mode === "edit") {
|
payload.roleId = state.roleId;
|
path = "/system/role/manage/edit";
|
}
|
var button = document.getElementById("saveRoleButton");
|
button.disabled = true;
|
apiRequest(path, {
|
method: "POST",
|
body: JSON.stringify(payload)
|
}).then(function () {
|
AppMessage.success("操作成功");
|
window.setTimeout(goBack, 450);
|
}).catch(function (error) {
|
AppMessage.error("操作失败:" + (error.message || "角色保存失败"));
|
}).then(function () {
|
button.disabled = false;
|
});
|
}
|
|
function getCheckedMenuIds() {
|
var ids = [];
|
document.querySelectorAll("#permissionTableBody input[type='checkbox']:checked").forEach(function (input) {
|
var value = Number(input.value || 0);
|
if (value && ids.indexOf(value) === -1) {
|
ids.push(value);
|
}
|
});
|
return ids;
|
}
|
|
function goBack() {
|
window.location.href = "./role-management.html";
|
}
|
|
function apiRequest(path, options) {
|
options = options || {};
|
var headers = options.headers || {};
|
var token = getToken();
|
if (token) {
|
headers.Authorization = "Bearer " + token;
|
}
|
if (!options.skipJson) {
|
headers["Content-Type"] = "application/json";
|
}
|
return fetch(getApiBaseUrl() + normalizePath(path), {
|
method: options.method || "GET",
|
headers: headers,
|
body: options.body
|
}).then(function (response) {
|
return response.json().catch(function () {
|
return { code: response.ok ? 200 : response.status, msg: response.statusText };
|
});
|
}).then(function (result) {
|
if (result.code === 401) {
|
clearLoginState();
|
redirectToLogin();
|
throw new Error(result.msg || "登录状态已过期");
|
}
|
if (result.code !== 200) {
|
throw new Error(result.msg || "请求失败");
|
}
|
return result;
|
});
|
}
|
|
function logout() {
|
apiRequest("/logout", {
|
method: "POST",
|
skipJson: true
|
}).catch(function () {
|
return null;
|
}).then(function () {
|
clearLoginState();
|
redirectToLogin();
|
});
|
}
|
|
function applyUserInfo(user) {
|
user = user || {};
|
var displayName = user.nickName || user.userName || user.username || "用户";
|
document.getElementById("userDisplayName").textContent = displayName;
|
document.querySelector(".user-avatar").textContent = displayName.substring(0, 1);
|
}
|
|
function readLoginUser() {
|
try {
|
var loginResult = JSON.parse(localStorage.getItem("visitor_admin_login_result") || "{}");
|
return (loginResult.userInfo && loginResult.userInfo.user) || loginResult.user || {};
|
} catch (error) {
|
return {};
|
}
|
}
|
|
function getApiBaseUrl() {
|
return trimRightSlash(localStorage.getItem("visitor_admin_api_base") || config.apiBaseUrl || window.location.origin);
|
}
|
|
function getToken() {
|
return localStorage.getItem("visitor_admin_token") || "";
|
}
|
|
function clearLoginState() {
|
localStorage.removeItem("visitor_admin_token");
|
localStorage.removeItem("visitor_admin_login_result");
|
localStorage.removeItem("visitor_admin_api_base");
|
}
|
|
function redirectToLogin() {
|
window.location.href = "../index.html";
|
}
|
|
function normalizePath(path) {
|
return "/" + String(path || "").replace(/^\/+/, "");
|
}
|
|
function trimRightSlash(value) {
|
return String(value || "").replace(/\/+$/, "");
|
}
|
|
function escapeHtml(value) {
|
return String(value == null ? "" : value).replace(/[&<>"']/g, function (char) {
|
return {
|
"&": "&",
|
"<": "<",
|
">": ">",
|
'"': """,
|
"'": "'"
|
}[char];
|
});
|
}
|
})();
|