您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
修复按钮尺寸问题,统一题目页和题单页的洛谷跳转功能
当前为
// ==UserScript== // @name 梦熊OJ自动跳题至洛谷 // @license MIT // @namespace http://tampermonkey.net/ // @version 2.1 // @description 修复按钮尺寸问题,统一题目页和题单页的洛谷跳转功能 // @author YourName // @match https://www.mxoj.net/problem/* // @match https://www.mxoj.net/training/problems* // @grant GM_addStyle // @grant GM_getResourceURL // @resource luoguIcon https://www.luogu.com.cn/favicon.ico // @icon https://www.luogu.com.cn/favicon.ico // ==/UserScript== (function() { 'use strict'; // 添加共用样式 GM_addStyle(` /* 共用洛谷按钮样式 */ .luogu-jump-btn { display: inline-flex; align-items: center; justify-content: center; padding: 6px 12px; background-color: #3498db; color: white !important; border-radius: 4px; font-size: 14px; font-weight: normal; text-decoration: none !important; vertical-align: middle; transition: all 0.2s; cursor: pointer; margin-left: 10px; height: 34px; /* 与提交按钮相同高度 */ line-height: 1.42857; /* Bootstrap默认行高 */ border: 1px solid transparent; white-space: nowrap; } .luogu-jump-btn:hover { background-color: #2980b9; transform: translateY(-1px); } .luogu-jump-btn::before { content: ""; display: inline-block; width: 16px; height: 16px; background-image: url(${GM_getResourceURL('luoguIcon')}); background-size: contain; background-repeat: no-repeat; vertical-align: middle; margin-right: 5px; } /* 题单页特定样式 */ .problem-title-container { display: inline-flex !important; align-items: center !important; } .luogu-hover-btn { display: none; width: 16px; height: 16px; margin-left: 6px; background-image: url(${GM_getResourceURL('luoguIcon')}); background-size: contain; background-repeat: no-repeat; cursor: pointer; vertical-align: middle; } .problem-title-container:hover .luogu-hover-btn { display: inline-block; } /* 隐藏原有箭头 */ .problem-title::after, .problem-title::before, a.problem-title::after, a.problem-title::before, .problem-title:hover::after, .problem-title:hover::before, a.problem-title:hover::after, a.problem-title:hover::before { display: none !important; content: none !important; } `); // 判断当前页面类型并执行相应功能 if (window.location.pathname.includes('/problem/') && !window.location.pathname.includes('/problems')) { initProblemPageScript(); // 题目详情页功能 } else if (window.location.pathname.includes('/training/problems')) { initProblemSetScript(); // 题单/题库页功能 } /**********************************/ /* 题目详情页功能 - 提交按钮旁添加跳转 */ /**********************************/ function initProblemPageScript() { // 查找提交按钮 function findSubmitButton() { const btn = document.querySelector('button.btn.btn-primary.answer[onclick^="goAnswer"]'); if (btn) { // 获取计算样式以确保尺寸匹配 const style = window.getComputedStyle(btn); return { element: btn, height: style.height, padding: style.padding, lineHeight: style.lineHeight, fontSize: style.fontSize }; } return null; } // 获取题目ID function getProblemId() { const submitButton = findSubmitButton(); if (submitButton && submitButton.element) { const onclickContent = submitButton.element.getAttribute('onclick') || ''; const match = onclickContent.match(/goAnswer\('([A-Za-z]+[\dA-Za-z]*)'\)/); if (match) return match[1]; } const urlMatch = window.location.pathname.match(/\/problem\/([A-Za-z]+[\dA-Za-z]*)/i); return urlMatch ? urlMatch[1] : null; } // 转换为洛谷题目ID function convertToLuoguId(problemId) { if (!problemId) return null; if (/^CF\d+[A-Za-z]?$/i.test(problemId)) { return problemId.toUpperCase(); } else if (/^L\d+$/i.test(problemId)) { return 'P' + problemId.substring(1); } return null; } // 插入洛谷按钮(精确匹配提交按钮样式) function insertLuoguButton(submitButtonInfo) { const submitButton = submitButtonInfo.element; if (!submitButton) return; // 避免重复添加 if (submitButton.nextElementSibling?.classList?.contains('luogu-jump-btn')) { return; } const problemId = getProblemId(); if (!problemId) return; const luoguId = convertToLuoguId(problemId); if (!luoguId) return; // 创建按钮并应用与提交按钮相同的尺寸 const button = document.createElement('a'); button.href = `https://www.luogu.com.cn/problem/${luoguId}`; button.textContent = '洛谷原题'; button.className = 'luogu-jump-btn'; button.target = '_blank'; // 精确应用提交按钮的样式 button.style.height = submitButtonInfo.height; button.style.padding = submitButtonInfo.padding; button.style.lineHeight = submitButtonInfo.lineHeight; button.style.fontSize = submitButtonInfo.fontSize; button.style.marginLeft = '10px'; // 插入到提交按钮后面 submitButton.parentNode.insertBefore(button, submitButton.nextSibling); } // 观察DOM变化 const observer = new MutationObserver(function() { const submitButtonInfo = findSubmitButton(); if (submitButtonInfo) { insertLuoguButton(submitButtonInfo); observer.disconnect(); } }); // 初始检查 const submitButtonInfo = findSubmitButton(); if (submitButtonInfo) { insertLuoguButton(submitButtonInfo); } else { observer.observe(document, { childList: true, subtree: true }); // 3秒后停止观察 setTimeout(() => { observer.disconnect(); const submitButtonInfo = findSubmitButton(); if (submitButtonInfo) { insertLuoguButton(submitButtonInfo); } }, 3000); } } /**********************************/ /* 题单/题库页功能 - 悬停显示跳转按钮 */ /**********************************/ function initProblemSetScript() { // 处理题目标题 function processProblemTitles() { const problemTitles = document.querySelectorAll('.problem-title, a[href*="/problem/"]'); problemTitles.forEach(title => { if (title.dataset.luoguProcessed) return; title.dataset.luoguProcessed = 'true'; // 创建标题容器 const container = document.createElement('div'); container.className = 'problem-title-container'; // 包装原有标题 title.parentNode.insertBefore(container, title); container.appendChild(title); // 从元素提取题目ID const problemId = extractProblemId(title); if (!problemId) return; // 转换为洛谷题目ID const luoguId = convertToLuoguId(problemId); if (!luoguId) return; // 添加悬停按钮 const luoguBtn = document.createElement('div'); luoguBtn.className = 'luogu-hover-btn'; luoguBtn.title = '在洛谷中查看此题'; luoguBtn.dataset.luoguId = luoguId; container.appendChild(luoguBtn); }); } // 提取题目ID function extractProblemId(titleElement) { if (titleElement.href) { const match = titleElement.href.match(/\/problem\/([A-Za-z]+[\dA-Za-z]*)/i); if (match) return match[1]; } const textMatch = titleElement.textContent.match(/([A-Za-z]+[\dA-Za-z]*)/); return textMatch ? textMatch[1] : null; } // 转换为洛谷题目ID function convertToLuoguId(problemId) { if (/^CF\d+[A-Za-z]?$/i.test(problemId)) { return problemId.toUpperCase(); } else if (/^L\d+$/i.test(problemId)) { return 'P' + problemId.substring(1); } return null; } // 事件委托处理点击 document.addEventListener('click', function(e) { const luoguBtn = e.target.closest('.luogu-hover-btn'); if (luoguBtn) { e.preventDefault(); const luoguId = luoguBtn.dataset.luoguId; if (luoguId) { window.open(`https://www.luogu.com.cn/problem/${luoguId}`, '_blank'); } } }); // 使用防抖观察器 const observer = new MutationObserver(function() { if (!window.luoguDebounce) { window.luoguDebounce = setTimeout(() => { processProblemTitles(); window.luoguDebounce = null; }, 100); } }); // 观察题目列表区域 const problemList = document.querySelector('.problem-list, .problems-container') || document.body; observer.observe(problemList, { childList: true, subtree: true }); // 初始处理 processProblemTitles(); } })();