您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
请配合 OI File Checker 使用
// ==UserScript== // @name Vscode 交互插件 // @description 请配合 OI File Checker 使用 // @namespace http://tampermonkey.net/ // @version 0.11 // @match https://www.luogu.com.cn/problem/* // @match https://codeforces.com/problemset/problem/*/* // @match https://codeforces.com/contest/*/problem/* // @match https://atcoder.jp/* // @match https://vjudge.net/* // @grant GM_xmlhttpRequest // @license MIT // ==/UserScript== (function() { 'use strict'; function addLgButton() { const containerSelector = 'div[data-v-f265fec6]'; const buttonSelector = 'button[data-v-505b6a97]'; function showSuccessToast(msg) { const body = document.body; const html = document.documentElement; const originalBodyClass = body.className; const originalHtmlClass = html.className; body.className = 'swal2-toast-shown swal2-shown'; html.className = 'no-js swal2-toast-shown swal2-shown'; if(document.querySelector('.swal2-container.send-success-toast')) return; const container = document.createElement('div'); container.className = 'swal2-container swal2-top-end swal2-backdrop-show send-success-toast'; container.style.overflowY = 'auto'; container.innerHTML = ` <div aria-labelledby="swal2-title" aria-describedby="swal2-html-container" class="swal2-popup swal2-toast swal2-icon-success swal2-show" tabindex="-1" role="alert" aria-live="polite" style="width: 100%; display: grid;"> <button type="button" class="swal2-close" aria-label="Close this dialog" style="display: none;">×</button> <ul class="swal2-progress-steps" style="display: none;"></ul> <div class="swal2-loader"></div> <div class="swal2-icon swal2-success swal2-icon-show" style="display: flex;"> <div class="swal2-success-circular-line-left" style="background-color: rgb(255, 255, 255);"></div> <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span> <div class="swal2-success-ring"></div> <div class="swal2-success-fix" style="background-color: rgb(255, 255, 255);"></div> <div class="swal2-success-circular-line-right" style="background-color: rgb(255, 255, 255);"></div> </div> <img class="swal2-image" style="display: none;"> <h2 class="swal2-title" id="swal2-title" style="display: block;">${msg}</h2> <div class="swal2-html-container" id="swal2-html-container" style="display: none;"></div> <!-- 其他隐藏元素保留 --> </div> `; document.body.appendChild(container); // 可选:设置几秒后自动消失 setTimeout(() => { container.remove(); body.className = originalBodyClass; html.className = originalHtmlClass; }, 2000); // 2秒 } function showErrorToast(msg) { const body = document.body; const html = document.documentElement; const originalBodyClass = body.className; const originalHtmlClass = html.className; body.className = 'swal2-toast-shown swal2-shown'; html.className = 'no-js swal2-toast-shown swal2-shown'; const container = document.createElement('div'); container.className = 'swal2-container swal2-top-end swal2-backdrop-show send-x-mark-toast'; container.style.overflowY = 'auto'; container.innerHTML = ` <div aria-labelledby="swal2-title" aria-describedby="swal2-html-container" class="swal2-popup swal2-toast swal2-icon-x-mark swal2-show" tabindex="-1" role="alert" aria-live="polite" style="width: 100%; display: grid;"> <button type="button" class="swal2-close" aria-label="Close this dialog" style="display: none;">×</button> <ul class="swal2-progress-steps" style="display: none;"></ul> <div class="swal2-loader"></div> <div class="swal2-icon swal2-error swal2-icon-show" style="display: flex;"> <span class="swal2-x-mark"> <span class="swal2-x-mark-line-left"></span> <span class="swal2-x-mark-line-right"></span> </span> </div> <img class="swal2-image" style="display: none;"> <h2 class="swal2-title" id="swal2-title" style="display: block;">${msg}</h2> <div class="swal2-html-container" id="swal2-html-container" style="display: none;"></div> <!-- 其他隐藏元素保留 --> </div> `; document.body.appendChild(container); // 可选:设置几秒后自动消失 setTimeout(() => { container.remove(); body.className = originalBodyClass; html.className = originalHtmlClass; }, 2000); // 2秒 } const container = document.querySelector(containerSelector); if (!container) return; const buttons = container.querySelectorAll(buttonSelector); if (buttons.length === 0) return; if (container.querySelector('.send-to-vscode-btn')) return; const lastButton = buttons[buttons.length - 1]; const newBtn = document.createElement('button'); newBtn.className = 'lform-size-middle button-transparent send-to-vscode-btn'; newBtn.setAttribute('type', 'button'); newBtn.setAttribute('data-v-505b6a97', ''); newBtn.setAttribute('data-v-f265fec6-s', ''); newBtn.innerText = '发送样例至 Vscode'; lastButton.insertAdjacentElement('afterend', newBtn); newBtn.addEventListener('click', () => { const codes = Array.from(document.querySelectorAll('pre.lfe-code')).map(el => el.innerText); const url = location.href; if(/^https:\/\/www\.luogu\.com\.cn\/problem\//.test(url) && !url.endsWith("#submit")) { GM_xmlhttpRequest({ method: "POST", url: "http://127.0.0.1:4000/send", headers: { "Content-Type": "application/json" }, data: JSON.stringify({ samples: codes }), onload: res => showSuccessToast('发送成功'), onerror: err => showErrorToast('发送失败') }); } else { showErrorToast('请回到题面再发送数据') } }); } function addCfButton() { if (document.getElementById("cf-send-btn")) return; function fadeOutAndRemove(el) { el.style.transition = "opacity 1s"; el.style.opacity = "0"; setTimeout(() => { if (el.parentNode) { el.parentNode.removeChild(el); } }, 800); } function show(msg) { let container = document.querySelector("#jGrowl.bottom-right.jGrowl"); if (!container) { container = document.createElement("div"); container.id = "jGrowl"; container.className = "bottom-right jGrowl"; // 先插入一个空的 jGrowl-notification(或者可以不加) const emptyNotification = document.createElement("div"); emptyNotification.className = "jGrowl-notification"; container.appendChild(emptyNotification); // 插入到 body 最后 document.body.appendChild(container); } // 创建通知 const notification = document.createElement("div"); notification.className = "jGrowl-notification default"; notification.style.display = "block"; notification.style.opacity = "0.8"; notification.innerHTML = ` <div class="close">×</div> <div class="header"></div> <div class="message">${msg}</div> `; // 关闭按钮逻辑 notification.querySelector(".close").addEventListener("click", () => { fadeOutAndRemove(notification); }); // 插入到容器最后 container.appendChild(notification); // 5秒后自动消失 setTimeout(() => { fadeOutAndRemove(notification); }, 5000); } const sidebar = document.getElementById("sidebar"); const box = document.createElement("div"); box.className = "roundbox sidebox borderTopRound"; box.innerHTML = ` <div class="caption titled"> → 复制数据到 VsCode <div class="top-links"></div> </div> <div style="text-align:center;margin:1em;"> <button id="cf-send-btn">发送</button> </div> `; sidebar.insertBefore(box, sidebar.firstChild); const btn = document.getElementById("cf-send-btn"); btn.addEventListener("click", () => { const samples = []; document.querySelectorAll(".sample-test").forEach(block => { const inputs = block.querySelectorAll(".input pre"); const outputs = block.querySelectorAll(".output pre"); inputs.forEach((inputEl, i) => { const outputEl = outputs[i]; if (outputEl) { samples.push(inputEl.innerText.trim()); samples.push(outputEl.innerText.trim()); } }); }); GM_xmlhttpRequest({ method: "POST", url: "http://127.0.0.1:4000/send", headers: { "Content-Type": "application/json" }, data: JSON.stringify({ samples: samples }), onload: res => { show('发送成功'); }, onerror: err => { show('发送失败'); } }); }); } function addAtButton() { if (!document.getElementById("task-statement")) return; if (document.getElementById("at-send-btn")) return; const col = Array.from(document.querySelectorAll("div.col-sm-12")) .find(div => div.id !== "contest-nav-tabs"); const spanH2 = col.querySelector("span.h2"); if (!spanH2) return; const btn = document.createElement("button"); btn.id = "at-send-btn"; btn.className = "btn btn-default btn-sm send-to-vscode-btn"; btn.textContent = "发送数据至 VsCode"; spanH2.appendChild(btn); btn.addEventListener("click", () => { const samples = []; document.querySelectorAll("section").forEach(section => { const h3 = section.querySelector("h3"); if (h3?.textContent.includes("Sample")) { const Text = section.querySelector("pre")?.textContent.trim(); samples.push(Text); } }); GM_xmlhttpRequest({ method: "POST", url: "http://127.0.0.1:4000/send", headers: { "Content-Type": "application/json" }, data: JSON.stringify({ samples: samples }) }); }); } function addVjButton() { if (document.getElementById("vj-send-btn")) return; const sidebar = document.getElementById("prob-operation"); const container = sidebar.querySelector("div.container"); const row = document.createElement("div"); row.classList.add("row"); container.appendChild(row); const new_div = document.createElement("div"); new_div.classList.add("col-xs-12"); row.appendChild(new_div); const btn = document.createElement("button"); btn.id = "vj-send-btn"; btn.className = "btn btn-secondary"; btn.type = "button" btn.textContent = "发送数据至 VsCode"; new_div.appendChild(btn); btn.addEventListener("click", () => { let iframe; if(document.getElementById("frame-description")) { iframe = document.getElementById("frame-description"); } else if(document.getElementById("frame-description-container")) { let iframes = document.getElementById("frame-description-container").querySelectorAll("iframe"); iframe = Array.from(iframes).find(iframe => { let style = window.getComputedStyle(iframe); return style.display !== "none"; }); console.log(iframe); } console.log(iframe); const innerDoc = iframe.contentDocument || iframe.contentWindow.document; const samples = []; const selector = innerDoc.getElementById("description-container"); selector.querySelectorAll("table.vjudge_sample tbody tr td pre").forEach(section => { samples.push(section.textContent.trim()); console.log(section.textContent.trim()); }); GM_xmlhttpRequest({ method: "POST", url: "http://127.0.0.1:4000/send", headers: { "Content-Type": "application/json" }, data: JSON.stringify({ samples: samples }) }); }); } if(location.hostname.includes("luogu.com.cn")) { const observer = new MutationObserver(() => addLgButton()); observer.observe(document.body, { childList: true, subtree: true }); addLgButton(); } else if(location.hostname.includes("codeforces.com")) { const observer = new MutationObserver(() => addCfButton()); observer.observe(document.body, { childList: true, subtree: true }); addCfButton(); } else if(location.hostname.includes("atcoder.jp")) { const observer = new MutationObserver(() => addAtButton()); observer.observe(document.body, { childList: true, subtree: true }); addAtButton(); } else if(location.hostname.includes("vjudge.net")) { const observer = new MutationObserver(() => addVjButton()); observer.observe(document.body, { childList: true, subtree: true }); addVjButton(); } })();