/** * 增强交互体验管理器 * 统一管理整个网站的交互优化 */ class EnhancedInteractionManager { constructor() { this.init(); } init() { this.setupGlobalInteractions(); this.setupLoadingStates(); this.setupFormEnhancements(); this.setupScrollEffects(); this.setupTooltips(); this.setupNotifications(); this.setupKeyboardNavigation(); this.setupMobileOptimizations(); } // 全局交互设置 setupGlobalInteractions() { // 平滑滚动 document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // 返回顶部按钮 this.createBackToTopButton(); // 页面加载进度条 this.createLoadingBar(); // 全局错误处理 this.setupGlobalErrorHandling(); } // 创建返回顶部按钮 createBackToTopButton() { const backToTop = document.createElement('button'); backToTop.innerHTML = ''; backToTop.className = 'btn-back-to-top'; backToTop.setAttribute('aria-label', '返回顶部'); const style = document.createElement('style'); style.textContent = ` .btn-back-to-top { position: fixed; bottom: 30px; right: 30px; width: 50px; height: 50px; background: #007bff; color: white; border: none; border-radius: 50%; cursor: pointer; opacity: 0; visibility: hidden; transition: all 0.3s ease; z-index: 1000; box-shadow: 0 4px 12px rgba(0,123,255,0.3); } .btn-back-to-top:hover { background: #0056b3; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,123,255,0.4); } .btn-back-to-top.show { opacity: 1; visibility: visible; } @media (max-width: 768px) { .btn-back-to-top { bottom: 20px; right: 20px; width: 45px; height: 45px; } } `; document.head.appendChild(style); document.body.appendChild(backToTop); // 滚动显示/隐藏 window.addEventListener('scroll', () => { if (window.pageYOffset > 300) { backToTop.classList.add('show'); } else { backToTop.classList.remove('show'); } }); // 点击返回顶部 backToTop.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); } // 创建加载进度条 createLoadingBar() { const loadingBar = document.createElement('div'); loadingBar.className = 'loading-bar'; const style = document.createElement('style'); style.textContent = ` .loading-bar { position: fixed; top: 0; left: 0; width: 0%; height: 3px; background: linear-gradient(90deg, #007bff, #28a745); z-index: 9999; transition: width 0.3s ease; } `; document.head.appendChild(style); document.body.appendChild(loadingBar); // 页面加载进度 let progress = 0; const interval = setInterval(() => { progress += Math.random() * 30; if (progress > 90) progress = 90; loadingBar.style.width = progress + '%'; }, 200); window.addEventListener('load', () => { clearInterval(interval); loadingBar.style.width = '100%'; setTimeout(() => { loadingBar.style.opacity = '0'; setTimeout(() => loadingBar.remove(), 300); }, 200); }); } // 设置加载状态 setupLoadingStates() { // 为所有按钮添加加载状态 document.addEventListener('click', (e) => { if (e.target.matches('button[type="submit"], .btn-primary, .btn-flower, .btn-animal')) { this.showButtonLoading(e.target); } }); } // 显示按钮加载状态 showButtonLoading(button) { const originalText = button.innerHTML; const originalDisabled = button.disabled; button.disabled = true; button.innerHTML = '处理中...'; // 模拟加载时间 setTimeout(() => { button.disabled = originalDisabled; button.innerHTML = originalText; }, 2000); } // 表单增强 setupFormEnhancements() { // 实时验证 document.querySelectorAll('input, textarea, select').forEach(field => { field.addEventListener('blur', () => this.validateField(field)); field.addEventListener('input', () => this.clearFieldError(field)); }); // 表单提交增强 document.querySelectorAll('form').forEach(form => { form.addEventListener('submit', (e) => { if (!this.validateForm(form)) { e.preventDefault(); } }); }); } // 验证单个字段 validateField(field) { const value = field.value.trim(); let isValid = true; let message = ''; // 必填验证 if (field.hasAttribute('required') && !value) { isValid = false; message = '此字段为必填项'; } // 邮箱验证 if (field.type === 'email' && value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) { isValid = false; message = '请输入有效的邮箱地址'; } // 手机号验证 if (field.type === 'tel' && value && !/^1[3-9]\d{9}$/.test(value)) { isValid = false; message = '请输入有效的手机号码'; } // 显示验证结果 if (!isValid) { this.showFieldError(field, message); } else { this.showFieldSuccess(field); } return isValid; } // 显示字段错误 showFieldError(field, message) { this.clearFieldFeedback(field); field.classList.add('is-invalid'); const feedback = document.createElement('div'); feedback.className = 'invalid-feedback'; feedback.textContent = message; field.parentNode.appendChild(feedback); } // 显示字段成功 showFieldSuccess(field) { this.clearFieldFeedback(field); field.classList.add('is-valid'); } // 清除字段错误 clearFieldError(field) { field.classList.remove('is-invalid'); const feedback = field.parentNode.querySelector('.invalid-feedback'); if (feedback) feedback.remove(); } // 清除字段反馈 clearFieldFeedback(field) { field.classList.remove('is-invalid', 'is-valid'); const feedback = field.parentNode.querySelector('.invalid-feedback, .valid-feedback'); if (feedback) feedback.remove(); } // 验证整个表单 validateForm(form) { let isValid = true; const fields = form.querySelectorAll('input, textarea, select'); fields.forEach(field => { if (!this.validateField(field)) { isValid = false; } }); return isValid; } // 滚动效果 setupScrollEffects() { // 导航栏滚动效果 const navbar = document.querySelector('.navbar'); if (navbar) { window.addEventListener('scroll', () => { if (window.scrollY > 100) { navbar.classList.add('navbar-scrolled'); } else { navbar.classList.remove('navbar-scrolled'); } }); // 添加滚动样式 const style = document.createElement('style'); style.textContent = ` .navbar-scrolled { background-color: rgba(255, 255, 255, 0.95) !important; backdrop-filter: blur(10px); box-shadow: 0 2px 10px rgba(0,0,0,0.1); transition: all 0.3s ease; } `; document.head.appendChild(style); } // 视差滚动效果 this.setupParallaxEffect(); } // 视差滚动效果 setupParallaxEffect() { const parallaxElements = document.querySelectorAll('.hero-section'); window.addEventListener('scroll', () => { const scrolled = window.pageYOffset; parallaxElements.forEach(element => { const rate = scrolled * -0.5; element.style.transform = `translateY(${rate}px)`; }); }); } // 工具提示 setupTooltips() { // 为所有带有title属性的元素添加工具提示 document.querySelectorAll('[title]').forEach(element => { element.addEventListener('mouseenter', (e) => { this.showTooltip(e.target, e.target.getAttribute('title')); }); element.addEventListener('mouseleave', () => { this.hideTooltip(); }); }); } // 显示工具提示 showTooltip(element, text) { const tooltip = document.createElement('div'); tooltip.className = 'custom-tooltip'; tooltip.textContent = text; const style = document.createElement('style'); style.textContent = ` .custom-tooltip { position: absolute; background: #333; color: white; padding: 8px 12px; border-radius: 4px; font-size: 14px; z-index: 1000; pointer-events: none; opacity: 0; transition: opacity 0.3s ease; } .custom-tooltip.show { opacity: 1; } `; if (!document.querySelector('style[data-tooltip]')) { style.setAttribute('data-tooltip', 'true'); document.head.appendChild(style); } document.body.appendChild(tooltip); const rect = element.getBoundingClientRect(); tooltip.style.left = rect.left + (rect.width / 2) - (tooltip.offsetWidth / 2) + 'px'; tooltip.style.top = rect.top - tooltip.offsetHeight - 10 + 'px'; setTimeout(() => tooltip.classList.add('show'), 10); } // 隐藏工具提示 hideTooltip() { const tooltip = document.querySelector('.custom-tooltip'); if (tooltip) { tooltip.classList.remove('show'); setTimeout(() => tooltip.remove(), 300); } } // 通知系统 setupNotifications() { this.createNotificationContainer(); } // 创建通知容器 createNotificationContainer() { const container = document.createElement('div'); container.id = 'notification-container'; const style = document.createElement('style'); style.textContent = ` #notification-container { position: fixed; top: 20px; right: 20px; z-index: 9999; max-width: 400px; } .notification { background: white; border-radius: 8px; padding: 16px; margin-bottom: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); border-left: 4px solid #007bff; opacity: 0; transform: translateX(100%); transition: all 0.3s ease; } .notification.show { opacity: 1; transform: translateX(0); } .notification.success { border-left-color: #28a745; } .notification.error { border-left-color: #dc3545; } .notification.warning { border-left-color: #ffc107; } .notification.info { border-left-color: #17a2b8; } `; document.head.appendChild(style); document.body.appendChild(container); } // 显示通知 showNotification(message, type = 'info', duration = 5000) { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.innerHTML = `