Spaces:
Running
Running
| /** | |
| * Magick 图像转换器 - 前端交互逻辑 | |
| * 功能:主题切换、文件上传、参数调整、表单提交 | |
| */ | |
| (function() { | |
| 'use strict'; | |
| // ========================================== | |
| // 1. 主题切换功能 | |
| // ========================================== | |
| const THEME_KEY = 'magick-theme-preference'; | |
| const themeBtns = document.querySelectorAll('.theme-btn'); | |
| const body = document.body; | |
| /** | |
| * 应用主题到页面 | |
| * @param {string} theme - 主题名称 (apple|glass|minimal|tech) | |
| */ | |
| function applyTheme(theme) { | |
| body.setAttribute('data-theme', theme); | |
| // 更新按钮激活状态 | |
| themeBtns.forEach(btn => { | |
| if (btn.dataset.theme === theme) { | |
| btn.classList.add('active'); | |
| } else { | |
| btn.classList.remove('active'); | |
| } | |
| }); | |
| // 保存到 localStorage | |
| try { | |
| localStorage.setItem(THEME_KEY, theme); | |
| } catch (e) { | |
| console.warn('无法保存主题偏好:', e); | |
| } | |
| } | |
| /** | |
| * 加载用户保存的主题偏好 | |
| */ | |
| function loadThemePreference() { | |
| try { | |
| const savedTheme = localStorage.getItem(THEME_KEY); | |
| if (savedTheme && ['apple', 'glass', 'minimal', 'tech'].includes(savedTheme)) { | |
| return savedTheme; | |
| } | |
| } catch (e) { | |
| console.warn('无法读取主题偏好:', e); | |
| } | |
| return 'apple'; // 默认主题 | |
| } | |
| // 初始化主题 | |
| const initialTheme = loadThemePreference(); | |
| applyTheme(initialTheme); | |
| // 绑定主题切换按钮事件 | |
| themeBtns.forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| const theme = btn.dataset.theme; | |
| applyTheme(theme); | |
| }); | |
| }); | |
| // ========================================== | |
| // 2. 文件上传交互 | |
| // ========================================== | |
| const fileInput = document.getElementById('fileInput'); | |
| const selectedFile = document.getElementById('selectedFile'); | |
| const fileInputWrapper = document.querySelector('.file-input-wrapper'); | |
| /** | |
| * 显示已选择的文件名 | |
| */ | |
| fileInput.addEventListener('change', function() { | |
| if (this.files.length > 0) { | |
| const file = this.files[0]; | |
| const fileName = file.name; | |
| const fileSize = (file.size / (1024 * 1024)).toFixed(2); // MB | |
| selectedFile.textContent = `✓ 已选择: ${fileName} (${fileSize} MB)`; | |
| } else { | |
| selectedFile.textContent = ''; | |
| } | |
| }); | |
| /** | |
| * 拖拽上传功能 | |
| */ | |
| fileInputWrapper.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| fileInputWrapper.style.borderColor = 'var(--color-primary)'; | |
| fileInputWrapper.style.background = 'var(--bg-input-hover)'; | |
| }); | |
| fileInputWrapper.addEventListener('dragleave', (e) => { | |
| e.preventDefault(); | |
| fileInputWrapper.style.borderColor = 'var(--border-color)'; | |
| fileInputWrapper.style.background = 'var(--bg-input)'; | |
| }); | |
| fileInputWrapper.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| fileInputWrapper.style.borderColor = 'var(--border-color)'; | |
| fileInputWrapper.style.background = 'var(--bg-input)'; | |
| const files = e.dataTransfer.files; | |
| if (files.length > 0) { | |
| fileInput.files = files; | |
| // 触发 change 事件以显示文件名 | |
| const event = new Event('change'); | |
| fileInput.dispatchEvent(event); | |
| } | |
| }); | |
| // ========================================== | |
| // 3. 质量参数滑块交互 | |
| // ========================================== | |
| const slider = document.getElementById('setting'); | |
| const sliderValue = document.getElementById('settingValue'); | |
| const paramHint = document.getElementById('paramHint'); | |
| const modeRadios = document.querySelectorAll('input[name="mode"]'); | |
| /** | |
| * 更新参数提示文本 | |
| */ | |
| function updateHint() { | |
| const mode = document.querySelector('input[name="mode"]:checked').value; | |
| const value = parseInt(slider.value); | |
| sliderValue.textContent = value; | |
| if (mode === 'lossy') { | |
| // 有损模式:质量提示 | |
| let quality = '中等'; | |
| if (value >= 90) quality = '极高'; | |
| else if (value >= 80) quality = '高'; | |
| else if (value >= 60) quality = '中等'; | |
| else if (value >= 40) quality = '中低'; | |
| else quality = '低'; | |
| paramHint.textContent = `质量: ${value} - ${quality}质量 (0=最低质量,100=最高质量)`; | |
| } else { | |
| // 无损模式:压缩速度提示 | |
| let speed = '平衡'; | |
| if (value <= 20) speed = '最慢/最佳压缩'; | |
| else if (value <= 40) speed = '较慢/较好压缩'; | |
| else if (value <= 60) speed = '平衡'; | |
| else if (value <= 80) speed = '较快/较差压缩'; | |
| else speed = '最快/最差压缩'; | |
| paramHint.textContent = `压缩速度: ${value} - ${speed} (0=最慢/最佳,100=最快/最差)`; | |
| } | |
| } | |
| // 滑块移动时更新 | |
| slider.addEventListener('input', updateHint); | |
| /** | |
| * 模式切换时自动调整质量值 | |
| */ | |
| modeRadios.forEach(radio => { | |
| radio.addEventListener('change', function() { | |
| const mode = document.querySelector('input[name="mode"]:checked').value; | |
| if (mode === 'lossless') { | |
| // 无损模式:默认最佳质量(0=最慢/最佳压缩) | |
| slider.value = 0; | |
| } else { | |
| // 有损模式:默认中等质量(80=高质量) | |
| slider.value = 80; | |
| } | |
| updateHint(); | |
| }); | |
| }); | |
| // 初始化提示 | |
| updateHint(); | |
| // ========================================== | |
| // 4. 表单提交处理 | |
| // ========================================== | |
| const form = document.getElementById('uploadForm'); | |
| const submitBtn = form.querySelector('.submit-btn'); | |
| const originalBtnText = submitBtn.textContent; | |
| form.addEventListener('submit', function(e) { | |
| // 显示加载状态 | |
| submitBtn.textContent = '⏳ 转换中...'; | |
| submitBtn.disabled = true; | |
| // 如果表单提交失败,需要恢复按钮状态 | |
| // 这里使用 setTimeout 作为后备方案 | |
| setTimeout(() => { | |
| if (submitBtn.disabled) { | |
| submitBtn.textContent = originalBtnText; | |
| submitBtn.disabled = false; | |
| } | |
| }, 60000); // 60秒超时恢复 | |
| }); | |
| // ========================================== | |
| // 5. 键盘快捷键 | |
| // ========================================== | |
| document.addEventListener('keydown', function(e) { | |
| // Ctrl/Cmd + K: 聚焦文件输入 | |
| if ((e.ctrlKey || e.metaKey) && e.key === 'k') { | |
| e.preventDefault(); | |
| fileInput.click(); | |
| } | |
| // Ctrl/Cmd + 1-4: 切换主题 | |
| if ((e.ctrlKey || e.metaKey) && e.key >= '1' && e.key <= '4') { | |
| e.preventDefault(); | |
| const themes = ['apple', 'glass', 'minimal', 'tech']; | |
| const themeIndex = parseInt(e.key) - 1; | |
| applyTheme(themes[themeIndex]); | |
| } | |
| }); | |
| // ========================================== | |
| // 6. 工具函数 - 参数验证 | |
| // ========================================== | |
| /** | |
| * 验证文件大小(客户端预检查) | |
| */ | |
| fileInput.addEventListener('change', function() { | |
| if (this.files.length > 0) { | |
| const file = this.files[0]; | |
| const maxSize = 200 * 1024 * 1024; // 200MB | |
| if (file.size > maxSize) { | |
| alert(`文件过大!最大支持 200MB,当前文件: ${(file.size / (1024 * 1024)).toFixed(2)} MB`); | |
| this.value = ''; // 清空选择 | |
| selectedFile.textContent = ''; | |
| return; | |
| } | |
| } | |
| }); | |
| // ========================================== | |
| // 7. 初始化完成提示 | |
| // ========================================== | |
| console.log('%c🧙♂️ Magick 图像转换器', 'font-size: 20px; font-weight: bold; color: #0071e3;'); | |
| console.log('%c✨ 前端已加载完成', 'color: #30d158;'); | |
| console.log('%c快捷键提示:', 'font-weight: bold;'); | |
| console.log(' Ctrl/Cmd + K: 打开文件选择'); | |
| console.log(' Ctrl/Cmd + 1-4: 切换主题 (1:Apple, 2:Glass, 3:Minimal, 4:Tech)'); | |
| })(); | |