diff --git a/Update.json b/Update.json index b1d2d6cf..96f64b2d 100644 --- a/Update.json +++ b/Update.json @@ -3113,6 +3113,17 @@ } ], "Notes": "因为它利用的bug被修复了" + }, + "2.4.4": { + "UpdateDate": 1759417362937, + "Prerelease": true, + "UpdateContents": [ + { + "PR": 866, + "Description": "比赛题目页面里左侧栏加入题目序号列表" + } + ], + "Notes": "#860 ..." } } } \ No newline at end of file diff --git a/XMOJ.user.js b/XMOJ.user.js index 812c41a0..69dfca7f 100644 --- a/XMOJ.user.js +++ b/XMOJ.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name XMOJ -// @version 2.4.3 +// @version 2.4.4 // @description XMOJ增强脚本 // @author @XMOJ-Script-dev, @langningchen and the community // @namespace https://github/langningchen @@ -1506,6 +1506,8 @@ async function main() { }, { "ID": "RefreshSolution", "Type": "F", "Name": "状态页面结果自动刷新每次只能刷新一个" }, {"ID": "CopyMD", "Type": "A", "Name": "复制题目或题解内容"}, { + "ID": "ProblemSwitcher", "Type": "A", "Name": "比赛题目切换器" + }, { "ID": "OpenAllProblem", "Type": "A", "Name": "比赛题目界面一键打开所有题目" }, { "ID": "CheckCode", "Type": "A", "Name": "提交代码前对代码进行检查", "Children": [{ @@ -1642,8 +1644,60 @@ async function main() { } } else if (location.pathname == "/problem.php") { await RenderMathJax(); - if (SearchParams.get("cid") != null) { + if (SearchParams.get("cid") != null && UtilityEnabled("ProblemSwitcher")) { document.getElementsByTagName("h2")[0].innerHTML += " (" + localStorage.getItem("UserScript-Contest-" + SearchParams.get("cid") + "-Problem-" + SearchParams.get("pid") + "-PID") + ")"; + let ContestProblemList = localStorage.getItem("UserScript-Contest-" + SearchParams.get("cid") + "-ProblemList"); + if (ContestProblemList == null) { + const contestReq = await fetch("https://www.xmoj.tech/contest.php?cid=" + SearchParams.get("cid")); + const res = await contestReq.text(); + if (contestReq.status === 200 && res.indexOf("比赛尚未开始或私有,不能查看题目。") === -1) { + const parser = new DOMParser(); + const dom = parser.parseFromString(res, "text/html"); + const rows = (dom.querySelector("#problemset > tbody")).rows; + let problemList = []; + for (let i = 0; i < rows.length; i++) { + problemList.push({ + "title": rows[i].children[2].innerText, + "url": rows[i].children[2].children[0].href + }); + } + localStorage.setItem("UserScript-Contest-" + SearchParams.get("cid") + "-ProblemList", JSON.stringify(problemList)); + ContestProblemList = JSON.stringify(problemList); + } + } + + let problemSwitcher = document.createElement("div"); + problemSwitcher.style.position = "fixed"; + problemSwitcher.style.top = "50%"; + problemSwitcher.style.left = "0"; + problemSwitcher.style.transform = "translateY(-50%)"; + problemSwitcher.style.maxHeight = "80vh"; + problemSwitcher.style.overflowY = "auto"; + if (document.querySelector("html").getAttribute("data-bs-theme") == "dark") { + problemSwitcher.style.backgroundColor = "rgba(0, 0, 0, 0.8)"; + } else { + problemSwitcher.style.backgroundColor = "rgba(255, 255, 255, 0.8)"; + } + problemSwitcher.style.padding = "10px"; + problemSwitcher.style.borderRadius = "0 10px 10px 0"; + problemSwitcher.style.display = "flex"; + problemSwitcher.style.flexDirection = "column"; + + let problemList = JSON.parse(ContestProblemList); + for (let i = 0; i < problemList.length; i++) { + let buttonText = ""; + if (i < 26) { + buttonText = String.fromCharCode(65 + i); + } else { + buttonText = String.fromCharCode(97 + (i - 26)); + } + let activeClass = ""; + if (problemList[i].url === location.href) { + activeClass = "active"; + } + problemSwitcher.innerHTML += `${buttonText}`; + } + document.body.appendChild(problemSwitcher); } if (document.querySelector("body > div > div.mt-3 > h2") != null) { document.querySelector("body > div > div.mt-3").innerHTML = "没有此题目或题目对你不可见"; diff --git a/package.json b/package.json index 8bee29cf..169470fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xmoj-script", - "version": "2.4.3", + "version": "2.4.4", "description": "an improvement script for xmoj.tech", "main": "AddonScript.js", "scripts": {