/** * PromptModal - 自定义 prompt/confirm 对话框 * 替代 window.prompt() / window.confirm()(Electron contextIsolation 下不可用) */ let overlayEl: HTMLElement | null = null; let titleEl: HTMLElement | null = null; let bodyEl: HTMLElement | null = null; let inputEl: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null = null; let okBtn: HTMLButtonElement | null = null; import { escapeHtml } from '../utils/utils.js'; let cancelBtn: HTMLButtonElement | null = null; let resolveFn: ((value: string | null) => void) | null = null; function ensureModal(): void { if (overlayEl) return; overlayEl = document.createElement('div'); overlayEl.className = 'modal-overlay'; overlayEl.id = 'promptModal'; overlayEl.style.display = 'none'; overlayEl.innerHTML = ` `; document.querySelector('#app')!.appendChild(overlayEl); titleEl = overlayEl.querySelector('#promptTitle')!; bodyEl = overlayEl.querySelector('#promptBody')!; okBtn = overlayEl.querySelector('#promptOk')! as HTMLButtonElement; cancelBtn = overlayEl.querySelector('#promptCancel')! as HTMLButtonElement; overlayEl.addEventListener('click', (e) => { if (e.target === overlayEl) close(null); }); cancelBtn.addEventListener('click', (e) => { e.stopPropagation(); close(null); }); okBtn.addEventListener('click', (e) => { e.stopPropagation(); if (inputEl instanceof HTMLSelectElement) { close(inputEl.value); } else if (inputEl) { close((inputEl as HTMLInputElement | HTMLTextAreaElement).value); } else { close(''); } }); document.addEventListener('keydown', (e) => { if (!overlayEl || overlayEl.style.display === 'none') return; if (e.key === 'Escape') { e.preventDefault(); close(null); } if (e.key === 'Enter' && !(inputEl instanceof HTMLTextAreaElement)) { e.preventDefault(); okBtn!.click(); } }); } function close(value: string | null): void { if (overlayEl) overlayEl.style.display = 'none'; if (resolveFn) { const r = resolveFn; resolveFn = null; r(value); } } /** 显示自定义 prompt,返回用户输入或 null(取消) */ export function showPrompt(options: { title: string; message?: string; defaultValue?: string; placeholder?: string; type?: 'text' | 'textarea' | 'select'; options?: Array<{ value: string; label: string }>; }): Promise { ensureModal(); return new Promise((resolve) => { resolveFn = resolve; titleEl!.textContent = options.title; let html = ''; if (options.message) { html += `

${escapeHtml(options.message)}

`; } if (options.type === 'select' && options.options) { html += ``; } else if (options.type === 'textarea') { html += ``; } else { html += ``; } bodyEl!.innerHTML = html; inputEl = bodyEl!.querySelector('#promptInput')! as HTMLInputElement; overlayEl!.style.display = ''; // 聚焦并选中文本 setTimeout(() => { if (inputEl instanceof HTMLInputElement) { inputEl.focus(); if (options.defaultValue) inputEl.select(); } else if (inputEl instanceof HTMLTextAreaElement) { inputEl.focus(); } }, 50); }); } /** 显示自定义 confirm,返回 true/false */ export function showConfirm(message: string, title = '确认'): Promise { ensureModal(); return new Promise((resolve) => { resolveFn = (val) => resolve(val !== null); titleEl!.textContent = title; bodyEl!.innerHTML = `

${escapeHtml(message)}

`; inputEl = null; overlayEl!.style.display = ''; okBtn!.focus(); }); }