// ==UserScript== // @name 悬浮球后台打开(修复版) // @namespace http://tampermonkey.net/ // @version 2.1 // @description 点击悬浮球开关后台模式,点一下开启,再点关闭 // @author You // @match *://*/* // @grant none // @downloadURL https://update.greasyfork.icu/scripts/575946/%E6%82%AC%E6%B5%AE%E7%90%83%E5%90%8E%E5%8F%B0%E6%89%93%E5%BC%80%EF%BC%88%E4%BF%AE%E5%A4%8D%E7%89%88%EF%BC%89.user.js // @updateURL https://update.greasyfork.icu/scripts/575946/%E6%82%AC%E6%B5%AE%E7%90%83%E5%90%8E%E5%8F%B0%E6%89%93%E5%BC%80%EF%BC%88%E4%BF%AE%E5%A4%8D%E7%89%88%EF%BC%89.meta.js // ==/UserScript== (function() { 'use strict'; // ========== 配置 ========== let bgMode = false; // 后台模式开关 let touchStartTime = 0; // 触摸开始时间 let touchMoved = false; // 是否移动过 let startX, startY; // ========== 创建悬浮球 ========== const ball = document.createElement('div'); ball.id = 'bgOpenBall'; ball.innerHTML = `
后台
模式
`; ball.style.cssText = ` position: fixed; width: 54px; height: 54px; z-index: 99999; cursor: pointer; touch-action: none; `; document.body.appendChild(ball); const ballInner = document.getElementById('ballInner'); // 读取上次保存的位置 try { const savedLeft = localStorage.getItem('bgBallLeft'); const savedTop = localStorage.getItem('bgBallTop'); if (savedLeft && savedTop && savedLeft !== 'null' && savedTop !== 'null') { ball.style.left = savedLeft; ball.style.top = savedTop; ball.style.right = 'auto'; ball.style.bottom = 'auto'; } else { // 默认右下角 ball.style.right = '20px'; ball.style.bottom = '100px'; } } catch(e) {} // ========== 更新悬浮球外观 ========== function updateBallAppearance() { if (bgMode) { ballInner.style.background = '#e53935'; ballInner.innerHTML = '后台
✓开启'; } else { ballInner.style.background = '#3a3a3a'; ballInner.innerHTML = '后台
模式'; } } // ========== 切换后台模式 ========== function toggleMode() { bgMode = !bgMode; updateBallAppearance(); if (bgMode) { showToast('✅ 后台模式已开启,点击链接自动后台打开'); } else { showToast('❌ 后台模式已关闭,链接正常打开'); } } // ========== 提示浮层 ========== let activeToast = null; function showToast(msg) { if (activeToast) activeToast.remove(); const toast = document.createElement('div'); toast.textContent = msg; toast.style.cssText = ` position: fixed; bottom: 170px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.85); color: #fff; padding: 10px 18px; border-radius: 30px; font-size: 14px; z-index: 100000; white-space: nowrap; pointer-events: none; font-family: system-ui, -apple-system, sans-serif; box-shadow: 0 2px 10px rgba(0,0,0,0.3); `; document.body.appendChild(toast); activeToast = toast; setTimeout(() => { if (toast && toast.remove) toast.remove(); if (activeToast === toast) activeToast = null; }, 1500); } // ========== 拖动逻辑 ========== let currentLeft = 0, currentTop = 0; let isDragging = false; ball.addEventListener('touchstart', function(e) { e.preventDefault(); const touch = e.touches[0]; // 获取当前位置 const leftVal = ball.style.left; const rightVal = ball.style.right; if (leftVal && leftVal !== 'auto') { currentLeft = parseFloat(leftVal); } else if (rightVal && rightVal !== 'auto') { currentLeft = window.innerWidth - ball.offsetWidth - parseFloat(rightVal); } else { currentLeft = window.innerWidth - ball.offsetWidth - 20; } currentTop = parseFloat(ball.style.top); if (isNaN(currentTop)) currentTop = window.innerHeight - ball.offsetHeight - 100; startX = touch.clientX - currentLeft; startY = touch.clientY - currentTop; touchStartTime = Date.now(); touchMoved = false; isDragging = false; }); ball.addEventListener('touchmove', function(e) { e.preventDefault(); const touch = e.touches[0]; let newLeft = touch.clientX - startX; let newTop = touch.clientY - startY; // 如果移动距离超过5px,认为是拖动 const moveDist = Math.abs(newLeft - currentLeft) + Math.abs(newTop - currentTop); if (moveDist > 5) { touchMoved = true; isDragging = true; } // 边界限制 newLeft = Math.max(0, Math.min(window.innerWidth - ball.offsetWidth, newLeft)); newTop = Math.max(0, Math.min(window.innerHeight - ball.offsetHeight, newTop)); ball.style.left = newLeft + 'px'; ball.style.top = newTop + 'px'; ball.style.right = 'auto'; ball.style.bottom = 'auto'; currentLeft = newLeft; currentTop = newTop; }); ball.addEventListener('touchend', function(e) { e.preventDefault(); const touchDuration = Date.now() - touchStartTime; // 保存位置 try { localStorage.setItem('bgBallLeft', ball.style.left); localStorage.setItem('bgBallTop', ball.style.top); } catch(e) {} // 如果没有移动且触摸时间小于300ms,认为是点击 if (!touchMoved && touchDuration < 300) { toggleMode(); } touchMoved = false; isDragging = false; }); // ========== 拦截链接点击,实现后台打开 ========== document.addEventListener('click', function(e) { if (!bgMode) return; // 后台模式未开启,不拦截 // 如果点的是悬浮球本身,不拦截(让toggleMode处理) if (ball.contains(e.target)) return; const link = e.target.closest('a'); if (!link) return; if (!link.href || link.href === '') return; if (link.href.startsWith('javascript:')) return; // 后台打开 e.preventDefault(); e.stopPropagation(); const newTab = window.open(link.href, '_blank'); if (newTab) { newTab.blur(); window.focus(); } // 震动反馈 if (navigator.vibrate) navigator.vibrate(30); // 可选:显示简短提示 // showToast('🔗 已后台打开'); }, true); // 使用捕获阶段 // 初始化外观 updateBallAppearance(); showToast('✨ 悬浮球已加载,点击开启后台模式'); })();