您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
为vJudge设置背景,并汉化部分界面
// ==UserScript== // @name vjudge++ // @namespace vjudge-plus-v2 // @version 1.8.4b12.6 // @description 为vJudge设置背景,并汉化部分界面 // @author axototl (original by Suntra) // @match https://vjudge.net/* // @noframes // @icon https://vjudge.net/favicon.ico // @license AGPLv3 or later // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @grant GM_info // @run-at document-end // ==/UserScript== 'use strict'; // license text: https://www.gnu.org/licenses/agpl-3.0.txt (() => { // 在基于 Blink 浏览器上检测是否为正常返回 if (GM_info.platform.browserName == "chrome" && performance.getEntries()[0].responseStatus != 200) return; let config = {}; function dbgopt(...txt) { if (config.debug) console.debug(txt.join(' ')); } function reloader() { alert("设置成功,刷新生效"); if (!navigator.onLine) { alert("离线状态,无法重加载。\n修改无法即刻生效"); return; } location.reload(); } // 初始化Getter / Setter (() => { const def_props = { experimental: false, debug: true, ads: true, enable_style: true, back: "https://cdn.luogu.com.cn/images/bg/fe/Day_And_Night_1.jpg", col: "#fff", collink: "#ff4c8c" } function getVal(key) { let gg = GM_getValue(key); if ('' === gg || undefined === gg) { let def = def_props[key]; GM_setValue(key, def); gg = def; } return gg; } for (let prop in def_props) { Object.defineProperty(config, prop, { get: () => getVal(prop), set: val => GM_setValue(prop, val) }); } })(); // 获取环境配置(不得异步处理) -Begin- (() => { function reg_command(name, prompts, need_reload = true) { let flag = true; GM_registerMenuCommand(prompts[config[name] | 0], () => { if (flag) { config[name] = !config[name]; flag = false; } if (need_reload) reloader(); }) } // 设置实验性功能 reg_command("experimental", ["× 点击启用实验性功能(界面汉化等)", "✔ 点击关闭实验性功能"]); // 设置debug reg_command("debug", ["已禁用 debug 输出", "已启用debug输出"], false); reg_command("ads", ["× 屏蔽广告(点击启用)", "✔ 屏蔽广告(点击禁用)"]); reg_command("enable_style", ["✖ 点击开启美化功能", '✔ 点击关闭美化功能']); // 禁用美化功能 if (!config.enable_style) return; // 设置背景 GM_registerMenuCommand("设置背景URL", () => { let tmp = window.prompt("请输入背景URL", config.back); if (null === tmp) { alert("未更改背景图片URL"); return; } config.back = tmp; GM_setValue("background", config.back); reloader(); }); // 设置文字颜色 const tester = /^#([0-9a-f]{3,6})$/i; function getColor(t) { let tmp; do { tmp = window.prompt("请输入颜色的Hexcode\n(比如#b93e3e)\n建议选择背景主色调的反差色", t); } while (null !== tmp && !tester.test(tmp) && '' !== tmp); if (null === tmp) tmp = t; return tmp; } GM_registerMenuCommand("设置文字颜色", () => { config.col = getColor(config.col); reloader(); }); GM_registerMenuCommand("设置链接背景颜色", () => { config.collink = getColor(config.collink); reloader(); }); })(); // 获取环境配置 -End- // 界面美化程序 -Begin- (async () => { if (!config.enable_style) return; document.body.innerHTML = "<div style='height: 60px'></div>" + document.body.innerHTML; // 防止顶栏和页面内容重叠 // User defined style GM_addStyle("body {background: url(" + config.back + ") no-repeat center top fixed;background-size: 100% 100%;-moz-background-size: 100% 100%;color: " + config.col + ";}" + "a:focus, a:hover, .active {&:not(.nav-link){color: " + config.collink + " !important;text-decoration: underline;}}"); // Global Style GM_addStyle( ".navbar {border-radius:0rem;background-color: rgba(0,0,0,65%) !important;position: fixed;top: 0;left: 0;z-index: 1000;width: 100%;}" + "scrollbar-width: none" + ".modal-content {background-color: rgba(255,255,255,90%);}" + ".form-control {background-color: rgba(255,255,255,50%);}" + ".tab-content {background-color: rgba(255,255,255,50%);border: 2px solid #eceeef;border-radius: 0.25rem;padding: 20px;}" + "table {background-color: rgba(255,255,255,70%);border-radius: 0.25rem;color: #000;}" ); GM_addStyle(".card-block, .card, .list-group-item, .btn-secondary, .page-link, .page-item.disabled .page-link, .dropdown-menu {background-color: rgba(255,255,255,0%) !important;}"); document.querySelector("body > div.body-footer").innerHTML += '<p style="color: #3fb98b">Theme powered by vjudge++ (original <a href="https://greatest.deepsurf.us/scripts/448801">vjudge+</a>)</p>'; })(); // 界面美化程序 -End- (async () => { if (!config.ads) return; let arr = document.querySelectorAll(".social, #prob-ads, #img-support"); for (let x of arr) x.remove(); })(); // 广告移除 // 界面汉化程序 -Begin- (async () => { if (!config.experimental) return; console.warn("未来版本将分离JSON文件,请注意"); const basicTranslateTable = { "#nav-problem > a": "问题列表", "#nav-status > a": "提交记录", "#nav-contest > a": "比赛", "#nav-workbook > a": "题单", "#nav-user > a": "用户", "#nav-group > a": "小组", "#nav-comment > a": "留言板", ".login": "登录", ".register": "注册", ".logout": "登出", ".user-dropdown > a:nth-child(1)": "个人主页", ".update-profile": "更新个人信息", ".message": "消息" }; const basicDynTransTable = { ".previous > a": "上一页", ".next > a": "下一页", "#filter": "应用过滤器", // 无法工作 "#reset": "重置过滤器", // 无法工作 }; const loginBoxTranslate = { "#loginModalLabel": "登录", "#btn-forget-password": "忘记密码", "#btn-login": "登录", ".btn[data-dismiss]": "取消" }; const registerBoxTrans = { "#registerModalLabel": "注册", "[for=register-username]": "用户名\n(必填)", "[for=register-password]": "密码\n(必填)", "[for=register-repeat-password]": "重复密码\n(必填)", "[for=register-nickname]": "昵称\n(可修改)", "[for=register-school]": "学校", "[for=register-email]": "邮箱\n(必填)", "[for=register-introduction]": "自我介绍", "[for=register-captcha]": "验证码\n(必填)", "#btn-register": "注册", ".btn[data-dismiss]": "取消" }; const updateProfileTrans = { "#updateModalLabel": "更新个人信息", "[for=update-username]": "用户名", "[for=update-orig-password]": "原密码(必填)", "[for=update-password]": "新密码\n(可选)", "[for=update-repeat-password]": "重复新密码", "[for=update-nickname]": "昵称", "[for=update-school]": "学校", "[for=update-captcha]": "验证码", "[for=update-email]": "邮箱", "[for=update-introduction]": "个人简介", "#btn-update-profile": "更新", ".btn[data-dismiss]": "取消" }; function upd_trans(tr, flag = false) { for (let prop in tr) { let k = document.querySelector(prop); if (null != k) if (flag && k.childNodes.length >= 1) k.childNodes[0].data = tr[prop]; else { k.innerText = tr[prop]; } else dbgopt(prop, "is null"); } } function dynamic_trans(table, triggerDOM = null) { let ev = "click"; if (null == triggerDOM) ev = "load", triggerDOM = window; triggerDOM.addEventListener(ev, () => setTimeout(() => upd_trans(table), 200)); } function reg_box_trans(triggerElem_selector, table) { let s = document.querySelector(triggerElem_selector); if (null != s) dynamic_trans(table, s); else dbgopt(triggerElem_selector, "is null"); } (async () => { document.querySelector(".navbar-brand").childNodes[2].data = " 首页"; upd_trans(basicTranslateTable); reg_box_trans(".login", loginBoxTranslate); reg_box_trans(".register", registerBoxTrans); reg_box_trans(".update-profile", updateProfileTrans); dynamic_trans(basicDynTransTable); })(); //基本汉化 // 静态内容汉化 /* -Begin- */ const staticTransTable = { "/": [{ "#index-intro > div > div > p": "Vritual Judge(以下简称vj)并不是一个真实的在线评测网站(以下简称OJ),\ 而是整合了各大OJ平台的题目形成的虚拟OJ平台。你提交的所有代码都会被发回原平台进行评测。\n\ vj可以让你轻松开展比赛,不再为测试数据发愁\n\n\ 目前我们支持以下平台的题库:" }, 0], "/problem": [{ "[data-category=all]": "全部问题", "[data-category=solved]": "已解决问题", '[data-category=favorites]': "收藏的问题", "[data-category=attempted]": "未通过/正在评测的问题" }, 1], "/status": [{ "[data-owner=all]": "所有提交", "[data-owner=mine]": "我的提交", ".username": "用户名", ".oj": "测评平台", ".prob_num": "问题编号", ".status": "状态", ".runtime": "运行时长", ".memory": "运行内存", ".length": "代码长度", ".language": "语言", ".date": "提交时间" }, 1], }; (async () => { for (const path in staticTransTable) { if (path == location.pathname) { const tr = staticTransTable[path] upd_trans(tr[0], tr[1]); break; } } })(); /* -End- */ })(); // 界面汉化程序 -End- })();