// ==UserScript== // @name 网页二维码强力识别 (Alt+点击) // @namespace http://tampermonkey.net/ // @version 2.0 // @description 按住 Alt 键点击网页上的图片即可识别二维码,完美绕过跨域限制。 // @author knighttools // @match *://*/* // @require https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @license MIT // @connect * // @downloadURL https://update.greasyfork.icu/scripts/571055/%E7%BD%91%E9%A1%B5%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%BC%BA%E5%8A%9B%E8%AF%86%E5%88%AB%20%28Alt%2B%E7%82%B9%E5%87%BB%29.user.js // @updateURL https://update.greasyfork.icu/scripts/571055/%E7%BD%91%E9%A1%B5%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%BC%BA%E5%8A%9B%E8%AF%86%E5%88%AB%20%28Alt%2B%E7%82%B9%E5%87%BB%29.meta.js // ==/UserScript== (function() { 'use strict'; // 监听全局点击事件 document.addEventListener('click', function(e) { // 必须按住 Alt 键,且点击的目标必须是图片 if (e.altKey && e.target.tagName.toUpperCase() === 'IMG') { e.preventDefault(); e.stopPropagation(); const img = e.target; showToast('⏳ 正在解析二维码...', 'blue'); // 尝试强制获取图片并解析 (绕过跨域) fetchImageAndDecode(img.src); } }, true); // 核心解析逻辑 function decodeImageData(imageObj) { const canvas = document.createElement('canvas'); canvas.width = imageObj.width; canvas.height = imageObj.height; const ctx = canvas.getContext('2d', { willReadFrequently: true }); ctx.drawImage(imageObj, 0, 0, canvas.width, canvas.height); try { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const code = jsQR(imageData.data, imageData.width, imageData.height); if (code && code.data) { // 识别成功,自动复制到剪贴板 GM_setClipboard(code.data, "text"); showToast(`✅ 识别成功并已复制到剪贴板!\n内容: ${code.data}`, 'green', 5000); } else { showToast('❌ 未在图片中发现二维码,或二维码太模糊。', 'orange'); } } catch (err) { showToast('❌ 解析失败: ' + err.message, 'red'); } } // 使用油猴的 GM_xmlhttpRequest 绕过跨域限制获取图片 function fetchImageAndDecode(url) { GM_xmlhttpRequest({ method: 'GET', url: url, responseType: 'blob', onload: function(response) { if (response.status === 200) { const blob = response.response; const blobUrl = URL.createObjectURL(blob); const tempImg = new Image(); tempImg.onload = function() { decodeImageData(tempImg); URL.revokeObjectURL(blobUrl); // 清理内存 }; tempImg.src = blobUrl; } else { showToast('❌ 图片加载失败,状态码: ' + response.status, 'red'); } }, onerror: function() { showToast('❌ 跨域请求被拦截或网络错误', 'red'); } }); } // 在屏幕顶部显示提示信息 (Toast) function showToast(text, color, duration = 3000) { // 移除旧的提示框 const oldToast = document.getElementById('qr-toast-msg'); if (oldToast) oldToast.remove(); const toast = document.createElement('div'); toast.id = 'qr-toast-msg'; toast.innerText = text; // 颜色映射 const colors = { 'blue': '#3b82f6', 'green': '#10b981', 'orange': '#f59e0b', 'red': '#ef4444' }; toast.style.cssText = ` position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: ${colors[color] || '#333'}; color: white; padding: 12px 20px; border-radius: 8px; font-size: 14px; z-index: 2147483647; box-shadow: 0 4px 6px rgba(0,0,0,0.1); max-width: 80%; word-break: break-all; pointer-events: none; transition: opacity 0.3s; `; document.body.appendChild(toast); // 自动消失 setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => toast.remove(), 300); }, duration); } })();