diff --git a/css/style.css b/css/style.css index 6115c37..2167604 100644 --- a/css/style.css +++ b/css/style.css @@ -31,7 +31,9 @@ html, body { } .btn { - padding: 10px 24px; + min-width: 72px; + height: 40px; + padding: 0 12px; font-size: 15px; border: 1px solid #ddd; border-radius: 6px; @@ -40,6 +42,9 @@ html, body { cursor: pointer; transition: all 0.2s; white-space: nowrap; + display: flex; + align-items: center; + justify-content: center; } .btn:active { @@ -47,6 +52,7 @@ html, body { } .btn-primary { + min-width: 100px; background: #4a90e2; color: #fff; border-color: #4a90e2; diff --git a/js/script.js b/js/script.js index 32c8fc4..f5aafdd 100644 --- a/js/script.js +++ b/js/script.js @@ -1766,7 +1766,7 @@ `; const tipText = document.createElement('p'); - tipText.textContent = '预览图片'; + tipText.textContent = '长按图片保存到相册'; tipText.style.cssText = ` color: #fff; font-size: 18px; @@ -1778,16 +1778,41 @@ img.src = dataUrl; img.style.cssText = ` max-width: 100%; - max-height: 80vh; + max-height: 70vh; border-radius: 8px; box-shadow: 0 4px 20px rgba(255,255,255,0.2); + -webkit-touch-callout: default; + -webkit-user-select: auto; + user-select: auto; `; + const btnContainer = document.createElement('div'); + btnContainer.style.cssText = ` + display: flex; + gap: 12px; + margin-top: 20px; + `; + + const saveBtn = document.createElement('button'); + saveBtn.textContent = '保存到相册'; + saveBtn.style.cssText = ` + padding: 12px 30px; + font-size: 16px; + background: #007AFF; + color: #fff; + border: none; + border-radius: 25px; + cursor: pointer; + `; + saveBtn.onclick = async () => { + tipOverlay.remove(); + await saveImageToGallery(dataUrl); + }; + const closeBtn = document.createElement('button'); closeBtn.textContent = '关闭'; closeBtn.style.cssText = ` - margin-top: 20px; - padding: 12px 40px; + padding: 12px 30px; font-size: 16px; background: #fff; color: #333; @@ -1797,12 +1822,70 @@ `; closeBtn.onclick = () => tipOverlay.remove(); + btnContainer.appendChild(saveBtn); + btnContainer.appendChild(closeBtn); tipOverlay.appendChild(tipText); tipOverlay.appendChild(img); - tipOverlay.appendChild(closeBtn); + tipOverlay.appendChild(btnContainer); document.body.appendChild(tipOverlay); } + // 保存图片到相册 + async function saveImageToGallery(dataUrl) { + const filename = '邀请函_' + Date.now() + '.png'; + + // 尝试使用 File System Access API (Android/Chrome) + if ('showSaveFilePicker' in window) { + try { + const blob = await (await fetch(dataUrl)).blob(); + const handle = await window.showSaveFilePicker({ + suggestedName: filename, + types: [{ + description: 'PNG 图片', + accept: { 'image/png': ['.png'] } + }] + }); + const writable = await handle.createWritable(); + await writable.write(blob); + await writable.close(); + showToast('图片已保存到相册'); + return; + } catch (err) { + console.log('File System Access API 失败,使用传统方式'); + } + } + + // 尝试使用 Web Share API (iOS Safari) + if (navigator.share && navigator.canShare) { + try { + const blob = await (await fetch(dataUrl)).blob(); + const file = new File([blob], filename, { type: 'image/png' }); + + if (navigator.canShare({ files: [file] })) { + await navigator.share({ + files: [file], + title: '邀请函', + text: '保存邀请函图片' + }); + showToast('图片已分享'); + return; + } + } catch (err) { + console.log('Web Share API 失败,使用传统方式'); + } + } + + // 传统下载方式 + const link = document.createElement('a'); + link.download = filename; + link.href = dataUrl; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + showToast('图片已保存,请在相册中查看'); + } + // 隐藏右键菜单 function hideContextMenu() { const existingMenu = document.getElementById('contextMenu'); @@ -2039,12 +2122,9 @@ cursor: pointer; margin-bottom: 12px; `; - saveBtn.onclick = () => { + saveBtn.onclick = async () => { tipOverlay.remove(); - const link = document.createElement('a'); - link.download = filename; - link.href = dataUrl; - link.click(); + await saveImageToGallery(dataUrl); }; const cancelBtn = document.createElement('button'); @@ -2096,6 +2176,44 @@ savePanel.insertBefore(previewBtn, saveBtn); } + // 显示 Toast 提示 + function showToast(message) { + const toast = document.createElement('div'); + toast.style.cssText = ` + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: rgba(0, 0, 0, 0.8); + color: #fff; + padding: 16px 24px; + border-radius: 8px; + font-size: 14px; + z-index: 10001; + pointer-events: none; + animation: fadeInOut 2s ease forwards; + `; + toast.textContent = message; + + // 添加动画样式 + if (!document.getElementById('toastStyle')) { + const style = document.createElement('style'); + style.id = 'toastStyle'; + style.textContent = ` + @keyframes fadeInOut { + 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.9); } + 20% { opacity: 1; transform: translate(-50%, -50%) scale(1); } + 80% { opacity: 1; transform: translate(-50%, -50%) scale(1); } + 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.9); } + } + `; + document.head.appendChild(style); + } + + document.body.appendChild(toast); + setTimeout(() => toast.remove(), 2000); + } + // 窗口大小改变时更新图片位置和边界 window.addEventListener('resize', () => { if (currentImage) {