(function () { if (window.appDialog) return; const state = { root: null, panel: null, title: null, message: null, field: null, input: null, cancel: null, confirm: null, lastFocused: null, queue: Promise.resolve() }; function ensureRoot() { if (state.root) return; const root = document.createElement('div'); root.className = 'tm-dialog-root'; root.hidden = true; root.innerHTML = [ '
', '' ].join(''); document.body.appendChild(root); state.root = root; state.panel = root.querySelector('.tm-dialog-panel'); state.title = root.querySelector('.tm-dialog-title'); state.message = root.querySelector('.tm-dialog-message'); state.field = root.querySelector('.tm-dialog-field'); state.input = root.querySelector('.tm-dialog-input'); state.cancel = root.querySelector('.tm-dialog-cancel'); state.confirm = root.querySelector('.tm-dialog-confirm'); } function whenReady() { if (document.body) return Promise.resolve(); return new Promise((resolve) => { document.addEventListener('DOMContentLoaded', resolve, { once: true }); }); } function normalizeOptions(type, value, fallbackValue) { if (value && typeof value === 'object' && !Array.isArray(value)) { return { type, title: value.title || (type === 'confirm' ? '请确认' : type === 'prompt' ? '请输入内容' : '系统提示'), message: value.message || '', confirmText: value.confirmText || (type === 'alert' ? '知道了' : '确定'), cancelText: value.cancelText || '取消', defaultValue: value.defaultValue == null ? '' : String(value.defaultValue), placeholder: value.placeholder || '' }; } return { type, title: type === 'confirm' ? '请确认' : type === 'prompt' ? '请输入内容' : '系统提示', message: value == null ? '' : String(value), confirmText: type === 'alert' ? '知道了' : '确定', cancelText: '取消', defaultValue: fallbackValue == null ? '' : String(fallbackValue), placeholder: '' }; } function setOpen(open) { ensureRoot(); state.root.hidden = !open; state.root.classList.toggle('is-open', open); } async function showDialog(options) { await whenReady(); ensureRoot(); return new Promise((resolve) => { setOpen(true); state.lastFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null; state.title.textContent = options.title; state.message.textContent = options.message; state.confirm.textContent = options.confirmText; state.cancel.textContent = options.cancelText; const isPrompt = options.type === 'prompt'; const showCancel = options.type !== 'alert'; state.field.hidden = !isPrompt; state.input.value = options.defaultValue || ''; state.input.placeholder = options.placeholder || ''; state.cancel.hidden = !showCancel; let settled = false; const close = (result, shouldRestoreFocus = true) => { if (settled) return; settled = true; document.removeEventListener('keydown', onKeydown, true); state.root.removeEventListener('click', onRootClick, true); setOpen(false); if (shouldRestoreFocus && state.lastFocused && typeof state.lastFocused.focus === 'function') { window.setTimeout(() => state.lastFocused.focus(), 0); } resolve(result); }; const onKeydown = (event) => { if (event.key === 'Escape') { event.preventDefault(); if (options.type === 'alert') close(undefined); else close(null); return; } if (event.key === 'Enter') { const target = event.target; if (target === state.cancel) return; event.preventDefault(); if (isPrompt) close(state.input.value); else if (options.type === 'confirm') close(true); else close(undefined); } }; const onRootClick = (event) => { const action = event.target && event.target.getAttribute && event.target.getAttribute('data-dialog-close'); if (action === 'cancel') { if (options.type === 'alert') close(undefined); else close(null); return; } if (event.target === state.cancel) { close(null); return; } if (event.target === state.confirm) { if (isPrompt) close(state.input.value); else if (options.type === 'confirm') close(true); else close(undefined); } }; document.addEventListener('keydown', onKeydown, true); state.root.addEventListener('click', onRootClick, true); window.setTimeout(() => { if (isPrompt) state.input.focus(); else state.confirm.focus(); }, 0); }).then((result) => { if (options.type === 'confirm') return result === true; if (options.type === 'prompt') return result == null ? null : String(result); return undefined; }); } function enqueue(task) { state.queue = state.queue.then(task, task); return state.queue; } const api = { alert(message) { return enqueue(() => showDialog(normalizeOptions('alert', message))); }, confirm(message) { return enqueue(() => showDialog(normalizeOptions('confirm', message))); }, prompt(message, defaultValue) { return enqueue(() => showDialog(normalizeOptions('prompt', message, defaultValue))); } }; window.appDialog = api; window.alert = function (message) { return api.alert(message); }; window.confirm = function (message) { return api.confirm(message); }; window.prompt = function (message, defaultValue) { return api.prompt(message, defaultValue); }; })();