// 对话框组件 - 负责各种确认对话框和选择器 export class DialogComponents { constructor() { this.addStyles(); } // 删除确认对话框 showDeleteConfirm(promptName, onConfirm) { return new Promise((resolve) => { const modal = this.createModal('delete-confirm-modal'); modal.innerHTML = `
`; this.bindDialogEvents(modal, { '.delete-confirm-btn': () => { if (onConfirm) onConfirm(); resolve(true); this.closeModal(modal); }, '.delete-cancel-btn': () => { resolve(false); this.closeModal(modal); } }); this.showModal(modal); }); } // 插入模式选择对话框 showInsertModeDialog(title = '选择插入模式', message = '检测到输入框中已有内容,请选择插入模式:') { return new Promise((resolve) => { let resolved = false; // 防止多次resolve const modal = this.createModal('insert-mode-modal'); modal.innerHTML = ` `; const resolveOnce = (value) => { if (!resolved) { resolved = true; this.closeModal(modal); resolve(value); } }; this.bindDialogEvents(modal, { '.option-card': (e) => { const action = e.currentTarget.getAttribute('data-action'); console.log('插入模式选择:', action); // 调试信息 resolveOnce(action); }, '.dialog-close-btn': () => { console.log('对话框关闭按钮点击'); // 调试信息 resolveOnce(null); } }); this.showModal(modal); }); } // 文本组件选择器对话框 showWidgetSelector(widgets, getDisplayName) { return new Promise((resolve) => { if (!Array.isArray(widgets) || widgets.length <= 1) { resolve(widgets[0] || null); return; } const modal = this.createModal('widget-selector-modal'); modal.innerHTML = ` `; this.bindDialogEvents(modal, { '.widget-option': (e) => { const index = parseInt(e.currentTarget.getAttribute('data-index')); resolve(widgets[index]); this.closeModal(modal); } }); this.showModal(modal); }); } // 导入文件选择对话框 showFileImportDialog(accept = '.json') { return new Promise((resolve) => { const input = document.createElement('input'); input.type = 'file'; input.accept = accept; input.style.display = 'none'; input.addEventListener('change', (e) => { const file = e.target.files[0]; resolve(file); document.body.removeChild(input); }); input.addEventListener('cancel', () => { resolve(null); document.body.removeChild(input); }); document.body.appendChild(input); input.click(); }); } // 成功提示对话框 showSuccessDialog(title, message, autoClose = 3000) { return new Promise((resolve) => { const modal = this.createModal('success-dialog-modal'); modal.innerHTML = ` `; this.bindDialogEvents(modal, { '.dialog-close-btn': () => { resolve(); this.closeModal(modal); } }); this.showModal(modal); // 自动关闭 if (autoClose) { setTimeout(() => { resolve(); this.closeModal(modal); }, autoClose); } }); } // 错误提示对话框 showErrorDialog(title, message) { return new Promise((resolve) => { const modal = this.createModal('error-dialog-modal'); modal.innerHTML = ` `; this.bindDialogEvents(modal, { '.error-ok-btn': () => { resolve(); this.closeModal(modal); } }); this.showModal(modal); }); } // 通用确认对话框 showConfirmDialog(title, message, confirmText = '确定', cancelText = '取消') { return new Promise((resolve) => { const modal = this.createModal('confirm-dialog-modal'); modal.innerHTML = ` `; this.bindDialogEvents(modal, { '.confirm-ok-btn': () => { resolve(true); this.closeModal(modal); }, '.confirm-cancel-btn': () => { resolve(false); this.closeModal(modal); } }); this.showModal(modal); }); } // 工具方法 createModal(className) { // 移除已存在的相同类型对话框 const existing = document.querySelector(`.${className}`); if (existing) { existing.remove(); } const modal = document.createElement('div'); modal.className = className; return modal; } showModal(modal) { document.body.appendChild(modal); // 添加显示动画 requestAnimationFrame(() => { modal.classList.add('show'); }); } closeModal(modal) { modal.classList.remove('show'); setTimeout(() => { if (modal.parentNode) { modal.parentNode.removeChild(modal); } }, 300); } bindDialogEvents(modal, eventMap) { // 绑定自定义事件 Object.entries(eventMap).forEach(([selector, handler]) => { const elements = modal.querySelectorAll(selector); elements.forEach(element => { element.addEventListener('click', handler); }); }); // 只有在没有自定义关闭按钮处理时才绑定通用关闭事件 if (!eventMap['.dialog-close-btn']) { const closeBtn = modal.querySelector('.dialog-close-btn'); if (closeBtn) { closeBtn.addEventListener('click', () => this.closeModal(modal)); } } const handleKeydown = (e) => { if (e.key === 'Escape') { // 如果有自定义关闭处理,使用它;否则直接关闭 if (eventMap['.dialog-close-btn']) { eventMap['.dialog-close-btn'](); } else { this.closeModal(modal); } document.removeEventListener('keydown', handleKeydown); } }; document.addEventListener('keydown', handleKeydown); } escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } truncateText(text, maxLength) { if (!text || text.length <= maxLength) return text; return text.substring(0, maxLength) + '...'; } addStyles() { const style = document.createElement('style'); style.textContent = ` /* 通用对话框样式 */ .delete-confirm-modal, .insert-mode-modal, .widget-selector-modal, .success-dialog-modal, .error-dialog-modal, .confirm-dialog-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 20000; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; } .delete-confirm-modal.show, .insert-mode-modal.show, .widget-selector-modal.show, .success-dialog-modal.show, .error-dialog-modal.show, .confirm-dialog-modal.show { opacity: 1; visibility: visible; } .dialog-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); display: flex; justify-content: center; align-items: center; backdrop-filter: blur(2px); } .dialog-container { background: #2b2b2b; border-radius: 12px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); max-width: 500px; width: 90%; max-height: 80vh; overflow: hidden; transform: scale(0.9); transition: transform 0.3s ease; } .delete-confirm-modal.show .dialog-container, .insert-mode-modal.show .dialog-container, .widget-selector-modal.show .dialog-container, .success-dialog-modal.show .dialog-container, .error-dialog-modal.show .dialog-container, .confirm-dialog-modal.show .dialog-container { transform: scale(1); } .dialog-header { padding: 20px 24px; border-bottom: 1px solid #404040; display: flex; justify-content: space-between; align-items: center; background: linear-gradient(135deg, #3a3a3a 0%, #2b2b2b 100%); } .dialog-header.success { background: linear-gradient(135deg, #43cf7c 0%, #38b86a 100%); } .dialog-header.error { background: linear-gradient(135deg, #ff5733 0%, #e04929 100%); } .dialog-header h4 { margin: 0; color: #ffffff; font-size: 16px; font-weight: 600; } .dialog-close-btn { background: none; border: none; color: #fff; font-size: 20px; cursor: pointer; padding: 4px; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 6px; transition: all 0.2s ease; } .dialog-close-btn:hover { background-color: rgba(255, 255, 255, 0.2); } .dialog-content { padding: 24px; color: #e0e0e0; line-height: 1.6; } .dialog-content p { margin: 0 0 16px 0; } .warning-text { color: #ff8c42; font-weight: 500; font-size: 14px; } .dialog-actions { display: flex; gap: 12px; margin-top: 20px; } .btn-primary, .btn-secondary, .btn-danger { padding: 10px 20px; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.2s ease; flex: 1; } .btn-primary { background: #2a82e4; color: white; } .btn-primary:hover { background: #1c6bb7; transform: translateY(-1px); } .btn-secondary { background: #6c757d; color: white; } .btn-secondary:hover { background: #5a6268; transform: translateY(-1px); } .btn-danger { background: #ff5733; color: white; } .btn-danger:hover { background: #e04929; transform: translateY(-1px); } /* 选项卡片样式 */ .option-cards { display: flex; flex-direction: column; gap: 12px; margin-top: 16px; } .option-card { background: #1a1a1a; border: 2px solid #404040; border-radius: 8px; padding: 16px; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; gap: 16px; } .option-card:hover { border-color: #2a82e4; background: #262626; transform: translateY(-2px); } .option-icon { font-size: 24px; flex-shrink: 0; } .option-title { font-weight: 600; color: #ffffff; margin-bottom: 4px; } .option-description { font-size: 13px; color: #888; line-height: 1.4; } /* 组件选择器样式 */ .widget-list { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; } .widget-option { background: #1a1a1a; border: 2px solid #404040; border-radius: 8px; padding: 12px; cursor: pointer; transition: all 0.2s ease; text-align: left; color: #e0e0e0; } .widget-option:hover { border-color: #2a82e4; background: #262626; } .widget-info { display: flex; flex-direction: column; gap: 4px; } .widget-name { font-weight: 500; color: #ffffff; } .widget-preview { font-size: 12px; color: #888; font-family: monospace; } /* 自动关闭指示器 */ .auto-close-indicator { margin-top: 16px; padding-top: 16px; border-top: 1px solid #404040; } .progress-bar { width: 100%; height: 3px; background: #404040; border-radius: 2px; overflow: hidden; margin-bottom: 8px; } .progress-fill { height: 100%; background: #43cf7c; width: 100%; animation: shrink linear forwards; transform-origin: right; } @keyframes shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } } /* 响应式设计 */ @media (max-width: 768px) { .dialog-container { margin: 20px; max-width: none; width: calc(100% - 40px); } .dialog-content { padding: 16px; } .option-cards { gap: 8px; } .option-card { padding: 12px; flex-direction: column; text-align: center; gap: 8px; } .dialog-actions { flex-direction: column; } } `; if (!document.head.querySelector('style[data-component="dialog-components"]')) { style.setAttribute('data-component', 'dialog-components'); document.head.appendChild(style); } } destroy() { // 移除所有对话框 const dialogs = document.querySelectorAll(` .delete-confirm-modal, .insert-mode-modal, .widget-selector-modal, .success-dialog-modal, .error-dialog-modal, .confirm-dialog-modal `); dialogs.forEach(dialog => { if (dialog.parentNode) { dialog.parentNode.removeChild(dialog); } }); // 移除样式 const style = document.head.querySelector('style[data-component="dialog-components"]'); if (style) { style.remove(); } } }