257 lines
7.3 KiB
JavaScript
257 lines
7.3 KiB
JavaScript
// 聊天室全局弹窗组件,提供 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.innerText = 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<void>}
|
|
*/
|
|
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<boolean>}
|
|
*/
|
|
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<string|null>}
|
|
*/
|
|
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?.();
|
|
}
|
|
});
|
|
|
|
// 点击遮罩层(弹窗外部)关闭弹窗
|
|
document.addEventListener("click", (event) => {
|
|
const modal = document.getElementById("global-dialog-modal");
|
|
if (!modal || modal.style.display === "none") return;
|
|
if (event.target === modal) {
|
|
// alert 模式直接隐藏,confirm/prompt 视为取消
|
|
if (currentDialogType === "alert") {
|
|
window.chatDialog?._hide?.();
|
|
} else {
|
|
window.chatDialog?._cancel?.();
|
|
}
|
|
}
|
|
});
|
|
}
|