您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
ZZULI 郑州轻工业大学在线评测系统,同一页上选题、看题、提交,方便使用
// ==UserScript== // @name ZZULIOJ 同一页上选题、看题、提交 // @namespace myt-zzuli-x-onSamePage // @version 0.7.2 // @description ZZULI 郑州轻工业大学在线评测系统,同一页上选题、看题、提交,方便使用 // @author Myitian // @license MIT // @match *://acm.zzuli.edu.cn/problemset.php* // @icon http://acm.zzuli.edu.cn/favicon.ico // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // ==/UserScript== /** * GET 请求 * @param {string} url 请求地址 * @param {string} responseType 响应类型 * @param {number} timeout 超时 * @returns {Promise<XMLHttpRequest>} Promise 对象,其 resolve 和 reject 均传入请求所用的 XMLHttpRequest 对象 */ function get(url, responseType = "document", timeout = 0) { return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.timeout = timeout; xhr.withCredentials = true; xhr.responseType = responseType; xhr.send(); xhr.onload = () => { if (xhr.status < 300) { resolve(xhr); } else { reject(xhr); } }; xhr.ontimeout = () => reject(timeout); }); } /** * @this {HTMLAnchorElement} * @param {Event} event */ function openSidebar(event) { event.preventDefault(); MYT_ZZULI_X.dataset.id = this.dataset.id; MYT_ZZULI_X.className = "x-shown"; refresh(); } /** * @this {HTMLIFrameElement} */ function cleanDocument() { if (!this.contentWindow) { return; } /** * @type {?HTMLElement} */ var e = this.contentWindow.document.querySelector(".container"); if (e) { e.style.width = "100%"; } e = this.contentWindow.document.querySelector("nav"); if (e) { e.style.display = "none"; } var es = this.contentWindow.document.querySelectorAll("a") for (var a of es) { if (!a.href.startsWith("javascript:")) { a.target = "_blank"; } } } /** * @param {string} url * @param {HTMLElement} node */ function loadCss(url, node) { var styles = `@import url("${url}");`; var lnk = document.createElement("link"); lnk.rel = "stylesheet"; lnk.href = "data:text/css," + encodeURIComponent(styles); node.appendChild(lnk); } /** * @param {string} url * @param {HTMLElement} node * @returns {Promise} */ function loadScript(url, node) { var script = document.createElement("script"); script.src = url; script.async = false; var callback = new Promise(resolve => script.addEventListener("load", resolve)); node.appendChild(script); return callback; } /** * @param {string} content * @param {HTMLElement} node */ function loadScriptContent(content, node) { var script = document.createElement("script"); script.innerHTML = content; node.appendChild(script); } /** * @param {HTMLElement} targetElement * @param {HTMLElement} buttonElement */ function toggleCustomElement(targetElement, buttonElement) { if (!(targetElement && buttonElement)) { return; } var c = targetElement.className; if (c.indexOf("x-hidden") >= 0) { targetElement.className = c.replace("x-hidden", "x-shown"); buttonElement.title = "收起"; } else if (c.indexOf("x-shown") >= 0) { targetElement.className = c.replace("x-shown", "x-hidden"); buttonElement.title = "展开"; } else { targetElement.className = c.trim().concat(" x-hidden"); buttonElement.title = "展开"; } } /** * @this {HTMLIFrameElement} */ function problemDocumentLoad() { if (!this.contentWindow) { return; } cleanDocument.call(this); var pid = new URLSearchParams(this.contentWindow.location.search).get("id") /** * @type {?HTMLSpanElement} */ var uid = this.contentWindow.document.querySelector("#profile"); /** * @type {HTMLDivElement} */ var codeDiv = this.contentWindow.document.querySelector(".jumbotron"); if (codeDiv && pid && uid && uid.innerText) { codeDiv.className = "panel panel-default x-shown"; codeDiv.innerHTML = ` <div class="panel-heading x-with-buttons"> <span>上次提交内容</span> <div class="x-button-container"> <button id="myt-zzuli-x-toggle-last-submit" class="x-myt-button x-myt-toggle" title="收起"></button> </div> </div> `; get(`http://acm.zzuli.edu.cn/status.php?problem_id=${pid}&user_id=${uid.innerText}`).then( xhr => { /** * @type {Document} */ var doc = xhr.response; var td = doc.querySelector("td"); if (td) { return get("http://acm.zzuli.edu.cn/showsource.php?id=" + td.innerText) } } ).then( xhr => { if (xhr instanceof XMLHttpRequest) { /** * @type {Document} */ var doc = xhr.response; var pre = doc.querySelector(".jumbotron pre"); codeDiv.appendChild(pre); /** * @type {NodeListOf<HTMLLinkElement>} */ var links = doc.querySelectorAll(".jumbotron link"); for (var link of links) { loadCss(link.href, codeDiv); } /** * @type {NodeListOf<HTMLScriptElement>} */ var scripts = doc.querySelectorAll(".jumbotron script[src]"); var callbacks = Array(scripts.length); var i = 0; for (var script of scripts) { callbacks[i] = loadScript(script.src, codeDiv); } Promise.all(callbacks).then(() => { loadScriptContent(`SyntaxHighlighter.config.space = " ";SyntaxHighlighter.highlight();`, codeDiv); }); } else { throw "无已提交内容!"; } } ).catch( e => { if (e instanceof XMLHttpRequest) { codeDiv.innerHTML += `<div class="panel-body content">${e.status} ${e.statusText}</div>`; } else if (e instanceof Error || e instanceof DOMException) { codeDiv.innerHTML += `<div class="panel-body content">${e.message}</div>`; } else if (typeof (e) == "number") { codeDiv.innerHTML += `<div class="panel-body content">响应超时 ${e}</div>`; } else if (typeof (e) == "string") { codeDiv.innerHTML += `<div class="panel-body content">${e}</div>`; } } ).finally( () => { var toggleLastSubmit = codeDiv.querySelector("#myt-zzuli-x-toggle-last-submit"); toggleLastSubmit.addEventListener("click", () => toggleCustomElement(codeDiv, toggleLastSubmit)); var style_overwrite = this.contentWindow.document.createElement("style"); style_overwrite.innerHTML = ` .syntaxhighlighter { max-height: 25em !important; } .syntaxhighlighter a, .syntaxhighlighter div, .syntaxhighlighter code, .syntaxhighlighter table, .syntaxhighlighter table td, .syntaxhighlighter table tr, .syntaxhighlighter table tbody, .syntaxhighlighter table thead, .syntaxhighlighter table caption, .syntaxhighlighter textarea { line-height: 1.25em !important; } .syntaxhighlighter .toolbar { right: 16px !important; } .panel-heading.x-with-buttons { display: flex; align-items: center; } .x-button-container { position: absolute; right: 2em; } button.x-myt-button { border: none; background: transparent no-repeat center center; width: 2em; height: 2em; border-radius: .3em; margin: .1em; cursor: pointer; transition: all 0.2s ease; } button.x-myt-button:active { background-color: #aaa; } button.x-myt-button:hover { background-color: #ccc; } .x-with-buttons .x-myt-toggle { transform: rotate(90deg); } .x-hidden .x-with-buttons .x-myt-toggle { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath stroke-linecap='round' d='M9 6l6 6 -6 6' fill='none' stroke-width='2' stroke='%23444'/%3E%3C/svg%3E"); } .x-shown .x-with-buttons .x-myt-toggle { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath stroke-linecap='round' d='M15 6l-6 6 6 6' fill='none' stroke-width='2' stroke='%23444'/%3E%3C/svg%3E"); } .x-hidden .panel-heading+div { max-height: 0; margin: 0; padding: 0; overflow: hidden; } `; codeDiv.appendChild(style_overwrite); } ) } } function toggle() { if (MYT_ZZULI_X.className == "x-hidden") { MYT_ZZULI_X.className = "x-shown"; document.querySelector("#myt-zzuli-x-toggle").title = "收起"; } else { MYT_ZZULI_X.className = "x-hidden"; document.querySelector("#myt-zzuli-x-toggle").title = "展开"; } } function refresh() { /** * @type {HTMLIFrameElement} */ var problem = MYT_ZZULI_X.querySelector("#myt-zzuli-x-problem"); /** * @type {HTMLIFrameElement} */ var submitpage = MYT_ZZULI_X.querySelector("#myt-zzuli-x-submitpage"); if (MYT_ZZULI_X.dataset.id) { problem.src = "http://acm.zzuli.edu.cn/problem.php?id=" + MYT_ZZULI_X.dataset.id; submitpage.src = "http://acm.zzuli.edu.cn/submitpage.php?id=" + MYT_ZZULI_X.dataset.id; } else { problem.src = ""; submitpage.src = ""; } } function settings() { var w = prompt("设置宽度", GM_getValue("myt-zzuli-x.width", "50%")); if (w) { MYT_ZZULI_X.style.setProperty("--width", w); GM_setValue("myt-zzuli-x.width", w); } } function newtab() { if (MYT_ZZULI_X.dataset.id) { window.open("http://acm.zzuli.edu.cn/problem.php?id=" + MYT_ZZULI_X.dataset.id, "_blank").focus(); } } /** * 主函数 */ function main() { /** * @type {NodeListOf<HTMLAnchorElement>} */ var problems = document.querySelectorAll("td:nth-child(3)>.left>a"); for (var problem of problems) { var i = problem.href.indexOf("id="); problem.dataset.id = problem.href.substring(i + 3); problem.addEventListener("click", openSidebar, true); } MYT_ZZULI_X.id = "myt-zzuli-x"; MYT_ZZULI_X.className = "x-hidden"; MYT_ZZULI_X.innerHTML = ` <div id="myt-zzuli-x-sidebar"> <ul> <button id="myt-zzuli-x-toggle" class="x-myt-button x-myt-toggle" title="展开"></button> <button id="myt-zzuli-x-refresh" class="x-myt-button x-myt-refresh" title="刷新"></button> <button id="myt-zzuli-x-settings" class="x-myt-button x-myt-settings" title="设置"></button> <button id="myt-zzuli-x-newtab" class="x-myt-button x-myt-newtab" title="在新标签页打开题目页面"></button> <!--<button id="myt-zzuli-x-ext" class="x-myt-button x-myt-ext" title="扩展功能按钮(预留)"></button>--> </ul> </div> <div id="myt-zzuli-x-iframecontainer"> <iframe id="myt-zzuli-x-problem"></iframe> <iframe id="myt-zzuli-x-submitpage"></iframe> </div> <style> #myt-zzuli-x { --width: ${GM_getValue("myt-zzuli-x.width", "50%")}; position: fixed; right: 0; top: 0px; width: var(--width); height: 100%; background: rgba(255, 255, 255, 0.5) none repeat scroll 0% 0%; z-index: 10; transition: all 0.5s ease; } #myt-zzuli-x.x-hidden { right: calc(-1*var(--width)); } #myt-zzuli-x.x-shown { right: 0; } #myt-zzuli-x-sidebar { position: absolute; right: 100%; background: white; border: solid 1px #428BCA; border-right: none; border-radius: 5px 0 0 5px; } #myt-zzuli-x ul { padding: .1em; text-align: center; margin: .1em; } button.x-myt-button { border: none; background: #eee no-repeat center center; width: 2em; height: 2em; border-radius: .3em; margin: .1em; cursor: pointer; transition: all 0.2s ease; } button.x-myt-button:hover { background-color: #ccc; } button.x-myt-button:active { background-color: #aaa; } #myt-zzuli-x.x-hidden .x-myt-toggle { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath stroke-linecap='round' d='M15 6l-6 6 6 6' fill='none' stroke-width='2' stroke='%23444'/%3E%3C/svg%3E"); } #myt-zzuli-x.x-shown .x-myt-toggle { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath stroke-linecap='round' d='M9 6l6 6 -6 6' fill='none' stroke-width='2' stroke='%23444'/%3E%3C/svg%3E"); } #myt-zzuli-x .x-myt-refresh { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23444' fill='none' stroke-linecap='round' stroke-width='2'%3E%3Cpath d='M6.804 10a6 6 0 0 1 10.392 0m-3 0h3V7m0 7a6 6 0 0 1-10.392 0m3 0h-3v3'/%3E%3C/svg%3E"); } #myt-zzuli-x .x-myt-settings { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23444'%3E%3Cg stroke-linecap='square' stroke-width='4'%3E%3Cpath d='M7 12H6'/%3E%3Cpath transform='rotate(45 12 12)' d='M7 12H6'/%3E%3Cpath d='M12 7V6'/%3E%3Cpath transform='rotate(45 12 12)' d='M12 7V6'/%3E%3Cpath d='M18 12h-1'/%3E%3Cpath transform='rotate(45 12 12)' d='M18 12h-1'/%3E%3Cpath d='M12 18v-1'/%3E%3Cpath transform='rotate(45 12 12)' d='M12 18v-1'/%3E%3C/g%3E%3Ccircle cx='12' cy='12' r='3' stroke-width='2' fill='none'/%3E%3C/svg%3E"); } #myt-zzuli-x .x-myt-newtab { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23444' fill='none' stroke-linecap='round' stroke-width='2'%3E%3Cpath d='M6 18a9 9 0 0 1 9-9h3m-3-3l3 3-3 3'/%3E%3C/svg%3E"); } #myt-zzuli-x-iframecontainer { height: 100%; width: 100%; border: solid 1px #428BCA; } #myt-zzuli-x iframe { height: 50%; width: 100%; display: block; border: solid 1px #428BCA; } </style> `; GM_registerMenuCommand("切换侧边栏展开状态", toggle); GM_registerMenuCommand("刷新侧边栏", refresh); GM_registerMenuCommand("设置侧边栏宽度", settings); GM_registerMenuCommand("在新标签页打开题目页面", newtab); GM_registerMenuCommand("清除本地存储", () => GM_deleteValue("myt-zzuli-x.width")); MYT_ZZULI_X.querySelector("#myt-zzuli-x-toggle").addEventListener("click", toggle); MYT_ZZULI_X.querySelector("#myt-zzuli-x-refresh").addEventListener("click", refresh); MYT_ZZULI_X.querySelector("#myt-zzuli-x-settings").addEventListener("click", settings); MYT_ZZULI_X.querySelector("#myt-zzuli-x-newtab").addEventListener("click", newtab); MYT_ZZULI_X.querySelector("#myt-zzuli-x-problem").addEventListener("load", problemDocumentLoad); MYT_ZZULI_X.querySelector("#myt-zzuli-x-submitpage").addEventListener("load", cleanDocument); document.body.appendChild(MYT_ZZULI_X); } const MYT_ZZULI_X = document.createElement("div"); main();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址