添加作者
// ==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.');
}
};
})();