// ==UserScript== // @name 通用自动点击脚本(定时版 + 状态显示) // @namespace http://tampermonkey.net/ // @version 3.2 // @description 支持定时自动点击,并通过鼠标右键选择目标元素,实时显示运行状态、执行次数等信息。 // @author Universal // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; const CONFIG = { CONTROL_PANEL_ID: 'autoClickControl', // 控制面板ID OVERLAY_ID: 'elementOverlay', // 高亮层ID CLICK_INTERVAL: 500, // 每次点击间隔 (毫秒) MAX_CLICKS: 20, // 最大点击次数 }; const State = { targetSelector: GM_getValue('targetSelector', ''), // 目标选择器 isPicking: false, // 是否正在选择目标元素 isRunning: false, // 是否正在运行点击 timer: null, // 定时器 clickCount: 0, // 当前点击次数 executeTime: GM_getValue('executeTime', ''), // 定时执行时间 debug: true, // 是否启用调试日志 }; // 调试日志 function debugLog(...args) { if (State.debug) console.log('[Debug]', ...args); } // 添加样式 function addStyles() { GM_addStyle(` #autoClickControl { position: fixed; top: 10px; right: 10px; z-index: 9999; background: #fff; border: 1px solid #ccc; padding: 15px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); font-family: Arial, sans-serif; width: 300px; } #autoClickControl input, #autoClickControl button { margin-bottom: 10px; } #autoClickControl input { width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 3px; } #autoClickControl button { padding: 5px 10px; border: none; border-radius: 3px; cursor: pointer; } #autoClickControl #startButton { background-color: #28a745; color: white; } #autoClickControl #pickButton { background-color: #007bff; color: white; } #autoClickControl #stopButton { background-color: #dc3545; color: white; } #elementOverlay { position: absolute; border: 2px dashed #007bff; background-color: rgba(0, 123, 255, 0.2); pointer-events: none; z-index: 9998; display: none; } #statusText { font-size: 12px; color: #333; } `); } // 创建控制面板 function createControlPanel() { if (document.getElementById(CONFIG.CONTROL_PANEL_ID)) return; const controlPanel = document.createElement('div'); controlPanel.id = CONFIG.CONTROL_PANEL_ID; controlPanel.innerHTML = `
状态: 未运行 | 点击次数: 0
`; document.body.appendChild(controlPanel); // 绑定事件 document.getElementById('pickButton').addEventListener('click', enableElementPicker); document.getElementById('startButton').addEventListener('click', startClicking); document.getElementById('stopButton').addEventListener('click', stopClicking); document.getElementById('targetSelectorInput').addEventListener('input', (event) => { State.targetSelector = event.target.value.trim(); GM_setValue('targetSelector', State.targetSelector); }); document.getElementById('executeTimeInput').addEventListener('change', (event) => { State.executeTime = event.target.value.trim(); GM_setValue('executeTime', State.executeTime); }); } // 更新状态文本 function updateStatus(message) { const statusText = document.getElementById('statusText'); statusText.innerText = `状态: ${message} | 点击次数: ${State.clickCount}`; } // 启用目标选择 function enableElementPicker() { alert('请右键单击页面上的目标元素来选择它。'); State.isPicking = true; document.addEventListener('mouseover', highlightElement, true); document.addEventListener('contextmenu', selectElement, true); } // 停用目标选择 function disableElementPicker() { State.isPicking = false; const overlay = document.getElementById(CONFIG.OVERLAY_ID); overlay.style.display = 'none'; document.removeEventListener('mouseover', highlightElement, true); document.removeEventListener('contextmenu', selectElement, true); } // 高亮鼠标悬停的元素 function highlightElement(event) { if (!State.isPicking) return; const overlay = document.getElementById(CONFIG.OVERLAY_ID); const target = event.target; if (!target) return; const rect = target.getBoundingClientRect(); overlay.style.display = 'block'; overlay.style.top = `${rect.top + window.scrollY}px`; overlay.style.left = `${rect.left + window.scrollX}px`; overlay.style.width = `${rect.width}px`; overlay.style.height = `${rect.height}px`; debugLog('Highlighting element:', target); } // 选择目标元素 function selectElement(event) { if (!State.isPicking) return; event.preventDefault(); const target = event.target; const selector = generateSelector(target); State.targetSelector = selector; GM_setValue('targetSelector', selector); document.getElementById('targetSelectorInput').value = selector; disableElementPicker(); alert(`目标元素已选择: ${selector}`); debugLog('Selected element:', target, 'Generated selector:', selector); } // 自动生成 CSS 选择器 function generateSelector(element) { if (!element) return null; let selector = element.tagName.toLowerCase(); if (element.id) { selector += `#${element.id}`; } else if (element.className) { const className = element.className.trim().split(/\s+/).join('.'); selector += `.${className}`; } return selector; } // 开始点击 function startClicking() { if (State.isRunning) return; const executeTime = new Date(State.executeTime).getTime(); const now = Date.now(); if (!State.targetSelector) { alert('请设置目标选择器!'); return; } if (!executeTime || executeTime <= now) { alert('请设置一个未来的执行时间!'); return; } const delay = executeTime - now; updateStatus(`等待 ${Math.ceil(delay / 1000)} 秒后执行`); debugLog('Scheduled to start in:', delay, 'ms'); State.timer = setTimeout(() => { State.isRunning = true; State.clickCount = 0; executeClicks(); }, delay); document.getElementById('stopButton').disabled = false; } // 停止点击 function stopClicking() { if (State.timer) clearTimeout(State.timer); State.isRunning = false; updateStatus('已停止'); document.getElementById('stopButton').disabled = true; debugLog('Stopped clicking.'); } // 执行点击 async function executeClicks() { const elements = document.querySelectorAll(State.targetSelector); if (elements.length === 0) { alert('未找到目标元素,点击操作终止!'); stopClicking(); return; } while (State.isRunning && State.clickCount < CONFIG.MAX_CLICKS) { for (const element of elements) { if (!State.isRunning) break; element.click(); State.clickCount++; updateStatus('运行中'); debugLog('Clicked element:', element, `Count: ${State.clickCount}`); await new Promise((resolve) => setTimeout(resolve, CONFIG.CLICK_INTERVAL)); } } stopClicking(); alert('点击操作完成!'); } // 创建高亮层 function createOverlay() { if (document.getElementById(CONFIG.OVERLAY_ID)) return; const overlay = document.createElement('div'); overlay.id = CONFIG.OVERLAY_ID; document.body.appendChild(overlay); } function initialize() { addStyles(); createControlPanel(); createOverlay(); } initialize(); })();