// ==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();
})();