(function () { var messageRoot = null; var activeConfirm = null; var menuIcons = { home: '', screen: '', device: '', people: '', map: '', log: '', account: '' }; initSidebarMenu(); window.AppMessage = { show: showMessage, success: function (text, options) { return showMessage("success", text || "操作成功", options); }, error: function (text, options) { return showMessage("error", text || "操作失败:失败原因说明", options); } }; window.AppConfirm = { open: openConfirm, close: closeConfirm }; function showMessage(type, text, options) { options = options || {}; var root = ensureMessageRoot(); var message = document.createElement("div"); var icon = document.createElement("span"); var content = document.createElement("span"); var duration = typeof options.duration === "number" ? options.duration : 1800; message.className = "app-message app-message-" + type; message.setAttribute("role", type === "error" ? "alert" : "status"); icon.className = "app-message-icon"; icon.innerHTML = type === "success" ? "✓" : "×"; content.className = "app-message-text"; content.textContent = text; message.appendChild(icon); message.appendChild(content); root.appendChild(message); window.setTimeout(function () { if (message.parentNode) { message.parentNode.removeChild(message); } }, duration); return message; } function ensureMessageRoot() { if (messageRoot && messageRoot.parentNode) { return messageRoot; } messageRoot = document.createElement("div"); messageRoot.className = "app-message-root"; document.body.appendChild(messageRoot); return messageRoot; } function openConfirm(options) { options = options || {}; closeConfirm(); var layer = document.createElement("div"); var mask = document.createElement("div"); var panel = document.createElement("section"); var icon = document.createElement("span"); var title = document.createElement("h3"); var message = document.createElement("p"); var actions = document.createElement("div"); var cancelButton = document.createElement("button"); var confirmButton = document.createElement("button"); layer.className = "app-confirm-layer"; mask.className = "app-confirm-mask"; panel.className = "app-confirm-panel"; panel.setAttribute("role", "dialog"); panel.setAttribute("aria-modal", "true"); icon.className = "app-confirm-icon"; icon.innerHTML = "×"; title.className = "app-confirm-title"; title.textContent = options.title || "是否确认删除数据?"; message.className = "app-confirm-message"; message.textContent = options.message || "删除操作不可撤回,请谨慎操作"; actions.className = "app-confirm-actions"; cancelButton.className = "app-confirm-button app-confirm-cancel"; cancelButton.type = "button"; cancelButton.textContent = options.cancelText || "取消"; confirmButton.className = "app-confirm-button app-confirm-submit"; confirmButton.type = "button"; confirmButton.textContent = options.confirmText || "确定"; actions.appendChild(cancelButton); actions.appendChild(confirmButton); panel.appendChild(icon); panel.appendChild(title); panel.appendChild(message); panel.appendChild(actions); layer.appendChild(mask); layer.appendChild(panel); document.body.appendChild(layer); activeConfirm = { layer: layer, onKeydown: function (event) { if (event.key === "Escape") { closeConfirm(); callHandler(options.onCancel); } } }; mask.addEventListener("click", function () { closeConfirm(); callHandler(options.onCancel); }); cancelButton.addEventListener("click", function () { closeConfirm(); callHandler(options.onCancel); }); confirmButton.addEventListener("click", function () { var result = callHandler(options.onConfirm); if (result && typeof result.then === "function") { confirmButton.disabled = true; result.then(closeConfirm).catch(function (error) { confirmButton.disabled = false; window.AppMessage.error(error && error.message ? "操作失败:" + error.message : "操作失败:请求处理失败"); }); return; } if (result !== false) { closeConfirm(); } }); document.addEventListener("keydown", activeConfirm.onKeydown); confirmButton.focus(); return layer; } function closeConfirm() { if (!activeConfirm) { return; } document.removeEventListener("keydown", activeConfirm.onKeydown); if (activeConfirm.layer && activeConfirm.layer.parentNode) { activeConfirm.layer.parentNode.removeChild(activeConfirm.layer); } activeConfirm = null; } function callHandler(handler) { if (typeof handler === "function") { return handler(); } return undefined; } function initSidebarMenu() { if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", bindSidebarMenu); return; } bindSidebarMenu(); } function bindSidebarMenu() { renderMenuIcons(); applyHomeMenuState(); document.querySelectorAll(".menu-group").forEach(function (group) { var title = group.querySelector(".menu-title"); if (!title || title.getAttribute("data-menu-bound") === "true") { return; } title.setAttribute("data-menu-bound", "true"); title.setAttribute("aria-expanded", String(group.classList.contains("open"))); title.addEventListener("click", function () { var opened = group.classList.toggle("open"); title.setAttribute("aria-expanded", String(opened)); }); }); } function applyHomeMenuState() { var activeHome = document.querySelector(".menu-item.active[href$='dashboard.html']"); if (!activeHome) { return; } document.querySelectorAll(".menu-group.open").forEach(function (group) { group.classList.remove("open"); }); } function renderMenuIcons() { document.querySelectorAll(".menu-icon").forEach(function (icon) { var key = Object.keys(menuIcons).find(function (name) { return icon.classList.contains(name); }); if (!key || icon.getAttribute("data-icon-rendered") === "true") { return; } icon.innerHTML = menuIcons[key]; icon.setAttribute("data-icon-rendered", "true"); }); } })();