// ==UserScript== // @name 公众号封面一键提取 // @version 1.4 // @description 点击悬浮按钮提取微信公众号文章高清封面,支持复制/下载/打开(下载文件名=文章标题) // @author 柒儿smile // @include *://mp.weixin.qq.com/s* // @match *://mp.weixin.qq.com/s* // @grant none // ==/UserScript== (function () { 'use strict'; // 提取封面原图链接 function getCoverImageUrl() { const meta = document.querySelector('meta[property="og:image"]'); if (!meta || !meta.content) return null; return meta.content.replace(/\/\d+$/, '/0'); } // 获取文章标题(去除公众号后缀) function getArticleTitle() { const titleEl = document.querySelector('.rich_media_title') || document.querySelector('h1') || document.querySelector('title'); if (!titleEl) return '公众号封面'; let title = titleEl.textContent.trim() // 移除常见后缀 .replace(/\s*[-||]\s*微信公众号.*$/, '') .replace(/\s*[-||]\s*微信公众平台.*$/, ''); // 过滤非法字符 title = title.replace(/[\\/:*?"<>|]/g, '_') .replace(/\s+/g, ' ') .trim(); return title.substring(0, 80) || '公众号封面'; } // 复制到剪贴板 async function copyToClipboard(text) { try { await navigator.clipboard.writeText(text); return true; } catch { const textarea = document.createElement('textarea'); textarea.value = text; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); const success = document.execCommand('copy'); document.body.removeChild(textarea); return success; } } // Toast 提示 function showToast(message, type = 'info') { const toast = document.createElement('div'); toast.textContent = message; Object.assign(toast.style, { position: 'fixed', top: '20px', left: '50%', transform: 'translateX(-50%)', background: type === 'error' ? 'rgba(245, 34, 45, 0.9)' : 'rgba(0,0,0,0.7)', color: 'white', padding: '10px 24px', borderRadius: '24px', fontSize: '14px', lineHeight: '1.4', zIndex: '9999999', backdropFilter: 'blur(10px)', whiteSpace: 'nowrap', animation: 'coverToastFadeIn 0.3s ease', pointerEvents: 'none' }); document.body.appendChild(toast); setTimeout(() => { toast.style.opacity = '0'; toast.style.transition = 'opacity 0.3s'; setTimeout(() => toast.remove(), 300); }, 1600); } // 下载图片(格式智能识别) async function downloadImage(url, fileName) { try { let ext = ''; const fmtMatch = url.match(/wx_fmt=(\w+)/); if (fmtMatch) { ext = fmtMatch[1].toLowerCase(); if (ext === 'jpeg') ext = 'jpg'; } else { const path = url.split('?')[0]; const lastSegment = path.split('/').pop(); if (lastSegment) { const dotIndex = lastSegment.lastIndexOf('.'); if (dotIndex > -1) { const candidate = lastSegment.substring(dotIndex + 1).toLowerCase(); if (/^(jpg|jpeg|png|gif|webp|bmp)$/.test(candidate)) { ext = candidate; } } } } if (!ext) ext = 'jpg'; const safeName = fileName.replace(/[\\/:*?"<>|]/g, '_').trim().substring(0, 80) || '公众号封面'; const response = await fetch(url); if (!response.ok) throw new Error('Network error'); const blob = await response.blob(); const blobUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = blobUrl; a.download = `${safeName}.${ext}`; document.body.appendChild(a); a.click(); document.body.removeChild(a); setTimeout(() => URL.revokeObjectURL(blobUrl), 1000); return true; } catch (e) { window.open(url, '_blank'); return false; } } // 弹窗 function showResultModal(coverUrl) { const oldModal = document.getElementById('cover-extractor-modal'); if (oldModal) oldModal.remove(); const modal = document.createElement('div'); modal.id = 'cover-extractor-modal'; modal.innerHTML = `
🖼️

封面提取成功

${coverUrl}
`; if (!document.getElementById('cover-modal-styles')) { const style = document.createElement('style'); style.id = 'cover-modal-styles'; style.textContent = ` .cover-modal-backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.4); backdrop-filter: blur(6px); display: flex; justify-content: center; align-items: center; z-index: 10000000; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; animation: coverFadeIn 0.2s ease; } .cover-modal-card { position: relative; background: rgba(255,255,255,0.95); backdrop-filter: blur(20px); border-radius: 20px; padding: 28px 24px 20px; width: 90%; max-width: 420px; box-shadow: 0 25px 50px rgba(0,0,0,0.25); animation: coverCardSlide 0.25s ease; } .cover-modal-close-btn { position: absolute; top: 12px; right: 12px; width: 32px; height: 32px; border-radius: 50%; background: rgba(0,0,0,0.05); border: none; font-size: 18px; color: #666; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background 0.2s; } .cover-modal-close-btn:hover { background: rgba(0,0,0,0.1); } .cover-modal-header { display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 20px; } .cover-modal-icon { font-size: 28px; } .cover-modal-title { margin: 0; font-size: 20px; font-weight: 600; color: #1a1a1a; } .cover-modal-url { background: #f0f2f5; border-radius: 12px; padding: 14px; margin-bottom: 24px; font-size: 14px; color: #555; word-break: break-all; max-height: 140px; overflow-y: auto; line-height: 1.5; } .cover-modal-actions { display: flex; gap: 10px; } .cover-btn-primary, .cover-btn-download, .cover-btn-secondary { flex: 1; padding: 10px 12px; border-radius: 12px; font-size: 15px; font-weight: 500; cursor: pointer; transition: all 0.2s; border: none; outline: none; white-space: nowrap; } .cover-btn-primary { background: #07c160; color: white; box-shadow: 0 2px 8px rgba(7,193,96,0.3); } .cover-btn-primary:hover { background: #06ad56; transform: translateY(-1px); } .cover-btn-download { background: #0d8bf1; color: white; box-shadow: 0 2px 8px rgba(13,139,241,0.3); } .cover-btn-download:hover { background: #0b7ad9; transform: translateY(-1px); } .cover-btn-secondary { background: #fff; color: #333; border: 1px solid #e0e0e0; } .cover-btn-secondary:hover { background: #f5f5f5; } @keyframes coverFadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes coverCardSlide { from { opacity: 0; transform: translateY(15px) scale(0.96); } to { opacity: 1; transform: translateY(0) scale(1); } } @keyframes coverToastFadeIn { from { opacity: 0; transform: translate(-50%, -10px); } to { opacity: 1; transform: translate(-50%, 0); } } `; document.head.appendChild(style); } const backdrop = modal.querySelector('.cover-modal-backdrop'); const copyBtn = modal.querySelector('#copy-btn'); const downloadBtn = modal.querySelector('#download-btn'); const openBtn = modal.querySelector('#open-btn'); const closeBtn = modal.querySelector('#close-btn-top'); const closeModal = () => { modal.remove(); document.removeEventListener('keydown', escHandler); }; backdrop.addEventListener('click', (e) => { if (e.target === backdrop) closeModal(); }); closeBtn.addEventListener('click', closeModal); copyBtn.addEventListener('click', async () => { const success = await copyToClipboard(coverUrl); if (success) { copyBtn.textContent = '✅ 已复制'; } else { copyBtn.textContent = '❌ 复制失败'; copyBtn.style.background = '#f5222d'; } setTimeout(closeModal, 800); }); downloadBtn.addEventListener('click', async () => { downloadBtn.textContent = '⏳ 下载中...'; downloadBtn.disabled = true; const title = getArticleTitle(); await downloadImage(coverUrl, title); closeModal(); }); openBtn.addEventListener('click', () => { window.open(coverUrl, '_blank'); closeModal(); }); const escHandler = (e) => { if (e.key === 'Escape') closeModal(); }; document.addEventListener('keydown', escHandler); document.body.appendChild(modal); } // 悬浮按钮 function createFloatingButton() { if (document.getElementById('cover-extractor-btn')) return; const btn = document.createElement('div'); btn.id = 'cover-extractor-btn'; btn.innerHTML = '📸'; btn.title = '提取公众号封面高清图'; Object.assign(btn.style, { position: 'fixed', bottom: '80px', right: '24px', width: '50px', height: '50px', borderRadius: '50%', background: 'rgba(255,255,255,0.7)', backdropFilter: 'blur(10px)', WebkitBackdropFilter: 'blur(10px)', border: '1px solid rgba(255,255,255,0.3)', boxShadow: '0 4px 16px rgba(0,0,0,0.12), 0 0 0 1px rgba(7,193,96,0.2)', color: '#07c160', fontSize: '26px', display: 'flex', justifyContent: 'center', alignItems: 'center', cursor: 'pointer', zIndex: '10000001', userSelect: 'none', transition: 'all 0.25s cubic-bezier(0.2, 0, 0, 1)' }); btn.addEventListener('mouseenter', () => { btn.style.transform = 'scale(1.15)'; btn.style.boxShadow = '0 8px 24px rgba(0,0,0,0.18), 0 0 0 2px rgba(7,193,96,0.3)'; btn.style.background = 'rgba(255,255,255,0.85)'; }); btn.addEventListener('mouseleave', () => { btn.style.transform = 'scale(1)'; btn.style.boxShadow = '0 4px 16px rgba(0,0,0,0.12), 0 0 0 1px rgba(7,193,96,0.2)'; btn.style.background = 'rgba(255,255,255,0.7)'; }); btn.addEventListener('click', () => { const coverUrl = getCoverImageUrl(); if (coverUrl) { showResultModal(coverUrl); } else { showToast('未找到封面图片,请确认页面是否正确', 'error'); } }); document.body.appendChild(btn); } function init() { createFloatingButton(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } const observer = new MutationObserver(() => { if (!document.getElementById('cover-extractor-btn')) { createFloatingButton(); } }); observer.observe(document.body, { childList: true, subtree: true }); })();