// ==UserScript== // @name 0755tt 稳定检测版(适配多次弹窗) // @namespace https://www.0755tt.com/ // @version 9.0 // @description 选正确→确定,1秒后选错误→确定,支持重复弹窗 // @author reese // @match https://www.0755tt.com/* // @grant none // ==/UserScript== (function() { 'use strict'; let isProcessing = false; let lastDialogCloseTime = 0; // 记录上次弹窗关闭时间,避免残留误判 const clickX = 914, clickY = 402; // 确认按钮坐标(可自行调整) function isDialogVisible() { // 检查选项是否存在且可见 const radios = document.querySelectorAll('.el-radio'); if (radios.length < 2) return false; // 检查第一个 radio 是否在视觉上可见(宽高大于0且未被隐藏) const firstRadio = radios[0]; if (firstRadio.offsetParent === null) return false; // 额外检查弹窗容器是否可见 const dialog = document.querySelector('.el-dialog'); return dialog !== null; } function selectRadio(index) { const radios = document.querySelectorAll('.el-radio'); if (!radios.length) return false; const target = radios[index]; target.click(); const input = target.querySelector('input[type="radio"]'); if (input) { input.checked = true; input.dispatchEvent(new Event('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); } console.log(`✅ 已选择选项 ${index + 1}: ${target.textContent.trim()}`); return true; } function simulateClick(x, y) { console.log(`🖱️ 在坐标 (${x}, ${y}) 模拟鼠标点击`); // 获取该坐标下的顶层元素 const target = document.elementFromPoint(x, y); if (!target) { console.warn('坐标处无元素'); return false; } console.log(` 目标元素: ${target.tagName}.${target.className}`); // 派发完整鼠标事件序列 const events = [ new PointerEvent('pointerdown', { bubbles: true, cancelable: true, clientX: x, clientY: y }), new MouseEvent('mousedown', { bubbles: true, cancelable: true, clientX: x, clientY: y }), new PointerEvent('pointerup', { bubbles: true, cancelable: true, clientX: x, clientY: y }), new MouseEvent('mouseup', { bubbles: true, cancelable: true, clientX: x, clientY: y }), new MouseEvent('click', { bubbles: true, cancelable: true, clientX: x, clientY: y }) ]; const element = document.elementFromPoint(x, y); if (element) { const clickEvent = new MouseEvent('click', {view: window,bubbles: true,cancelable: true,clientX: x,clientY: y}); element.dispatchEvent(clickEvent); } else { console.log("未找到对应坐标的元素"); } events.forEach(event => target.dispatchEvent(event)); return true; } function doSequence() { if (isProcessing) return; isProcessing = true; // 第一步:选正确并确认 selectRadio(0); setTimeout(() => simulateClick(clickX, clickY), 100); // 1秒后第二步 setTimeout(() => { // 重新检查弹窗是否还在(可能已关闭) if (!isDialogVisible()) { console.warn('弹窗已提前关闭,跳过第二步'); isProcessing = false; return; } selectRadio(1); setTimeout(() => simulateClick(clickX, clickY), 100); // 完成标记 setTimeout(() => { isProcessing = false; lastDialogCloseTime = Date.now(); console.log('✅ 流程完成,等待下一次弹窗'); }, 2000); }, 1000); } // 主循环:每 500ms 检查一次弹窗 setInterval(() => { if (isProcessing) return; // 弹窗关闭后 3 秒内不触发(防止弹窗关闭动画导致的误判) if (Date.now() - lastDialogCloseTime < 3000) return; if (isDialogVisible()) { console.log('🔔 检测到弹窗'); doSequence(); } }, 500); // 同时保留 MutationObserver 作为补充(处理弹窗通过插入新节点出现的情况) const observer = new MutationObserver(mutations => { for (const m of mutations) { if (!m.addedNodes.length) continue; for (const node of m.addedNodes) { if (node.nodeType !== 1) continue; if (node.querySelectorAll('.el-radio').length >= 2) { if (!isProcessing && Date.now() - lastDialogCloseTime >= 3000) { console.log('🔔 DOM 新增弹窗'); doSequence(); } return; } } } }); observer.observe(document.body, { childList: true, subtree: true }); // 页面加载时可能有初始弹窗 window.addEventListener('load', () => { setTimeout(() => { if (!isProcessing && isDialogVisible() && Date.now() - lastDialogCloseTime >= 3000) { doSequence(); } }, 2000); }); })();