// 聊天室全局弹窗组件,提供 alert / confirm / prompt API 与按钮事件绑定。 let globalDialogEventsBound = false; let dialogResolve = null; let currentDialogType = "alert"; /** * 按 ID 读取全局弹窗节点。 * * @param {string} id * @returns {HTMLElement|null} */ function getDialogElement(id) { return document.getElementById(id); } /** * 打开弹窗并按模式同步标题、内容、输入框和按钮状态。 * * @param {object} options * @param {string} options.message * @param {string} options.title * @param {string} options.color * @param {string} options.type * @param {string} [options.defaultVal] * @param {string} [options.confirmText] * @param {string} [options.cancelText] * @returns {void} */ function openDialog({ message, title, color, type, defaultVal, confirmText, cancelText }) { currentDialogType = type; const header = getDialogElement("global-dialog-header"); const messageBox = getDialogElement("global-dialog-message"); const confirmButton = getDialogElement("global-dialog-confirm-btn"); const inputWrap = getDialogElement("global-dialog-input-wrap"); const inputElement = getDialogElement("global-dialog-input"); const cancelButton = getDialogElement("global-dialog-cancel-btn"); const modal = getDialogElement("global-dialog-modal"); if (!header || !messageBox || !confirmButton || !inputWrap || !(inputElement instanceof HTMLTextAreaElement) || !cancelButton || !modal) { return; } header.textContent = title; header.style.background = color; messageBox.textContent = message; confirmButton.style.background = color; confirmButton.textContent = confirmText || "确定"; cancelButton.textContent = cancelText || "取消"; if (type === "prompt") { inputElement.value = defaultVal ?? ""; inputWrap.style.display = ""; window.setTimeout(() => { inputElement.focus(); inputElement.select(); }, 80); } else { inputWrap.style.display = "none"; inputElement.value = ""; } cancelButton.style.display = type === "confirm" || type === "prompt" ? "" : "none"; confirmButton.style.flex = type === "alert" ? "1 1 100%" : "1"; modal.style.display = "flex"; } /** * 隐藏弹窗并重置 Promise 回调状态。 * * @returns {void} */ function hideDialog() { const modal = getDialogElement("global-dialog-modal"); if (modal) { modal.style.display = "none"; } dialogResolve = null; currentDialogType = "alert"; } /** * 创建兼容旧调用点的全局 chatDialog API。 * * @returns {object} */ function createChatDialogApi() { return { /** * 显示提示弹窗。 * * @param {string} message * @param {string} title * @param {string} color * @returns {Promise} */ alert(message, title = "提示", color = "#336699") { return new Promise((resolve) => { dialogResolve = resolve; openDialog({ message, title, color, type: "alert" }); }); }, /** * 显示确认弹窗。 * * @param {string} message * @param {string} title * @param {string} color * @param {string} confirmText * @param {string} cancelText * @returns {Promise} */ confirm(message, title = "请确认", color = "#cc4444", confirmText = "确定", cancelText = "取消") { return new Promise((resolve) => { dialogResolve = resolve; openDialog({ message, title, color, type: "confirm", confirmText, cancelText }); }); }, /** * 显示文本输入弹窗。 * * @param {string} message * @param {string} defaultVal * @param {string} title * @param {string} color * @returns {Promise} */ prompt(message, defaultVal = "", title = "请输入", color = "#336699") { return new Promise((resolve) => { dialogResolve = resolve; openDialog({ message, title, color, type: "prompt", defaultVal }); }); }, /** * 确认当前弹窗。 * * @returns {void} */ _confirm() { if (currentDialogType === "prompt") { dialogResolve?.(getDialogElement("global-dialog-input")?.value ?? ""); } else if (currentDialogType === "confirm") { dialogResolve?.(true); } else { dialogResolve?.(); } hideDialog(); }, /** * 取消当前弹窗。 * * @returns {void} */ _cancel() { dialogResolve?.(currentDialogType === "prompt" ? null : false); hideDialog(); }, /** * 直接隐藏当前弹窗。 * * @returns {void} */ _hide() { hideDialog(); }, }; } /** * 确保全局 chatDialog API 已挂载。 * * @returns {void} */ function ensureChatDialog() { if (!window.chatDialog) { window.chatDialog = createChatDialogApi(); } } /** * 绑定全局弹窗确认与取消按钮。 * * @returns {void} */ export function bindGlobalDialogControls() { if (globalDialogEventsBound || typeof document === "undefined") { return; } globalDialogEventsBound = true; ensureChatDialog(); document.addEventListener("click", (event) => { if (!(event.target instanceof Element)) { return; } const actionButton = event.target.closest("[data-chat-dialog-action]"); if (!actionButton) { return; } event.preventDefault(); const action = actionButton.getAttribute("data-chat-dialog-action"); // 全局弹窗只允许确认/取消两类动作,继续承接旧 Promise 回调流程。 if (action === "confirm") { window.chatDialog?._confirm?.(); return; } if (action === "cancel") { window.chatDialog?._cancel?.(); } }); document.addEventListener("keydown", (event) => { if (!(event.target instanceof HTMLTextAreaElement) || event.target.id !== "global-dialog-input") { return; } // prompt 输入框沿用旧体验:Enter 确认,Shift+Enter 保留换行,Esc 取消。 if (event.key === "Enter" && !event.shiftKey) { event.preventDefault(); window.chatDialog?._confirm?.(); return; } if (event.key === "Escape") { event.preventDefault(); window.chatDialog?._cancel?.(); } }); }