您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
添加作者
// ==UserScript== // @name Pinnacle Optimize // @namespace http://tampermonkey.net/ // @version 0.5 // @description 添加作者 // @author Lycoiref & xgay231 // @match *://app.pinnacle.run/* // @icon https://www.google.com/s2/favicons?sz=64&domain=mjclouds.com // @license MIT // @grant none // ==/UserScript== (function () { 'use strict'; let optionsRows = []; let btns = []; let currentQuestionTextElement = null; // 存储当前问题文本元素 let transformingContainer = null; let mainContentArea = null; // 封装更健壮的点击事件模拟函数,模拟完整的鼠标点击过程 function simulateFullClick(element) { if (!element) { console.error('simulateFullClick called with null or undefined element.'); return; } try { // 获取元素的位置和大小,计算中心点作为点击坐标 const rect = element.getBoundingClientRect(); const clientX = rect.left + rect.width / 2; const clientY = rect.top + rect.height / 2; const commonEventProps = { bubbles: true, cancelable: true, view: window, clientX: clientX, clientY: clientY }; // 1. 模拟 mouseover 事件 (可选,但有时有用) element.dispatchEvent(new MouseEvent('mouseover', commonEventProps)); // 2. 模拟 mousedown 事件 element.dispatchEvent(new MouseEvent('mousedown', commonEventProps)); console.log('Dispatched mousedown to:', element); // 3. 模拟 mouseup 事件 element.dispatchEvent(new MouseEvent('mouseup', commonEventProps)); console.log('Dispatched mouseup to:', element); // 4. 模拟 click 事件 (这是最终触发交互的事件) element.dispatchEvent(new MouseEvent('click', commonEventProps)); console.log('Dispatched click to:', element); // 模拟 mouseout 事件 (可选,但有时有用) element.dispatchEvent(new MouseEvent('mouseout', commonEventProps)); } catch (e) { console.error('Error dispatching full click event:', e); } } // 封装更新DOM元素引用的函数 function updateElements() { // 尝试找到当前活跃的题目包装器(通过transform: none 或 translateX(0px)判断) const activeWrapper = document.querySelector( '.h-full.bg-default-555[style*="transform: none"], ' + '.h-full.bg-default-555[style*="transform: translateX(0px)"], ' + '.h-full.bg-default-555[style*="transform: translate3d(0px, 0px, 0px)"], ' + // 兜底方案:如果上述选择器都找不到,就找第一个可见的 .question-card 的父级 '.h-full.bg-default-555:not([style*="opacity: 0"])' ); let questionElement = null; let optionsList = []; if (activeWrapper) { questionElement = activeWrapper.querySelector('.whitespace-pre-line'); optionsList = activeWrapper.querySelectorAll('.select-row'); } else { // 如果没有找到活跃的包装器,直接查找页面上的第一个 console.warn('Active question wrapper not found. Falling back to general queries.'); questionElement = document.querySelector('.whitespace-pre-line'); optionsList = document.querySelectorAll('.select-row'); } currentQuestionTextElement = questionElement; // 更新全局问题元素引用 optionsRows = optionsList; // 更新全局选项行引用 btns = document.querySelectorAll('button'); // 总是获取所有按钮 console.log('Elements updated:', { optionsRows, btns, question: currentQuestionTextElement ? currentQuestionTextElement.innerText : 'N/A', activeWrapper: activeWrapper // 调试用 }); } window.onload = async () => { await new Promise((resolve) => setTimeout(resolve, 100)); // 持续等待关键DOM元素出现 while (!document.querySelector('.select-row') || !document.querySelector('button') || !document.querySelector('.whitespace-pre-line')) { console.log('Waiting for essential elements...'); await new Promise((resolve) => setTimeout(resolve, 100)); } // 首次加载时更新所有元素引用 updateElements(); console.log('Initial elements fetched.'); // 页面刷新机制(防卡死) setInterval(() => { let cards = document.querySelectorAll('p'); cards.forEach((card) => { if (card.innerText.includes('题库市场')) { console.log('Detected "题库市场" card, reloading page to prevent being stuck.'); window.location.reload(); } }); }, 500); window.addEventListener('keypress', (e) => { const keyLower = e.key.toLowerCase(); const targetIndex = ['q', 'w', 'e', 'r'].indexOf(keyLower); if (targetIndex !== -1) { // 检查整个选项组是否被禁用 const optionsGroupParent = optionsRows[targetIndex]?.closest('[data-sentry-component="OptionsGroup"]'); if (optionsGroupParent && optionsGroupParent.classList.contains('disabled')) { console.log('Options group is disabled. Cannot select a new option.'); return; } if (optionsRows[targetIndex]) { const clickableTarget = optionsRows[targetIndex].querySelector('section.content') || optionsRows[targetIndex]; if (clickableTarget) { console.log(`Attempting to click option ${targetIndex + 1} with key '${keyLower}':`, clickableTarget); simulateFullClick(clickableTarget); // 使用 simulateFullClick } else { console.warn(`Clickable target (section.content) not found within option row ${targetIndex + 1}.`); } } else { console.warn(`Option row for key '${keyLower}' (index ${targetIndex}) not found. There might be fewer options.`); } } if (e.key === ' ') { e.preventDefault(); console.log('Spacebar pressed. Current buttons:', btns); let nextButton = null; let submitButton = null; for (let i = 0; i < btns.length; i++) { const btnText = btns[i].innerText; if (btnText.includes('下一题')) { nextButton = btns[i]; } if (btnText.includes('提交')) { submitButton = btns[i]; } } if (nextButton && !nextButton.disabled) { simulateFullClick(nextButton); // 使用 simulateFullClick console.log('Clicked "下一题" button.'); } else if (submitButton && !submitButton.disabled) { simulateFullClick(submitButton); // 使用 simulateFullClick console.log('Clicked "提交" button.'); } else { console.log('No clickable "下一题" or "提交" button found, or they are disabled.'); } document.activeElement.blur(); } }); // MutationObserver 的目标是整体内容区域或包含动画的容器 transformingContainer = document.querySelector('.h-full.bg-default-555[draggable="false"]'); mainContentArea = document.querySelector('.flex-grow.flex.flex-col.mx-auto.w-full.max-w-lg'); const observerTarget = mainContentArea; // 观察最外层稳定区域 if (observerTarget) { let observer = new MutationObserver((mutations) => { let shouldUpdate = false; for (const mutation of mutations) { // 检查是否有子节点增删,或者文本内容变化 (在题目卡片内部) if (mutation.type === 'childList' || mutation.type === 'characterData') { // 检查变化是否发生在题目相关的元素内部 const targetElement = mutation.target; if (targetElement.closest('.question-card') || targetElement.matches('.question-card') || targetElement.closest('.select-row') || targetElement.matches('.select-row') || (currentQuestionTextElement && (targetElement === currentQuestionTextElement || currentQuestionTextElement.contains(targetElement)))) { shouldUpdate = true; break; } } // 检查 transform 样式变化,因为这是题目切换的关键信号 if (mutation.type === 'attributes' && mutation.attributeName === 'style' && transformingContainer && mutation.target === transformingContainer) { const newTransform = mutation.target.style.transform; if (newTransform && newTransform !== mutation.oldValue) { console.log('Transforming container style changed. Potential question switch.'); shouldUpdate = true; break; } } } if (shouldUpdate) { // 添加一个短延迟,确保动画完成和DOM稳定 clearTimeout(window.pinnacleUpdateTimer); window.pinnacleUpdateTimer = setTimeout(() => { console.log('Delayed updateElements triggered.'); updateElements(); }, 200); // 200毫秒延迟,可根据动画时间调整 } }); observer.observe(observerTarget, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'], // 监听 style 和 class 属性 characterData: true }); console.log('MutationObserver started on:', observerTarget); } else { console.warn('Neither transforming container nor main content area found for MutationObserver.'); } }; })();