(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 = '' + renderCheck(row.module) + ""; } return [ "", moduleCell, "" + renderCheck(row.page) + "", "" + row.actions.map(renderCheck).join("") + "", "" ].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 [ '" ].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]; }); } })();