diff --git a/resources/js/chat-room/dialog.js b/resources/js/chat-room/dialog.js index d5d555a..df6e857 100644 --- a/resources/js/chat-room/dialog.js +++ b/resources/js/chat-room/dialog.js @@ -1,6 +1,183 @@ -// 聊天室全局弹窗事件绑定,替代 Blade 内联 onclick。 +// 聊天室全局弹窗组件,提供 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] + * @returns {void} + */ +function openDialog({ message, title, color, type, defaultVal }) { + 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; + + 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 + * @returns {Promise} + */ + confirm(message, title = "请确认", color = "#cc4444") { + return new Promise((resolve) => { + dialogResolve = resolve; + openDialog({ message, title, color, type: "confirm" }); + }); + }, + + /** + * 显示文本输入弹窗。 + * + * @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(); + } +} /** * 绑定全局弹窗确认与取消按钮。 @@ -13,6 +190,8 @@ export function bindGlobalDialogControls() { } globalDialogEventsBound = true; + ensureChatDialog(); + document.addEventListener("click", (event) => { if (!(event.target instanceof Element)) { return; diff --git a/resources/views/chat/partials/global-dialog.blade.php b/resources/views/chat/partials/global-dialog.blade.php index dd473ac..25b615b 100644 --- a/resources/views/chat/partials/global-dialog.blade.php +++ b/resources/views/chat/partials/global-dialog.blade.php @@ -93,131 +93,3 @@ opacity: .88; } - -