// ==UserScript== // @name 粉笔网刷题宝 // @namespace http://tampermonkey.net/ // @version 0.0.52 // @author binyellow // @icon https://nodestatic.fbstatic.cn/weblts_spa_online/page/assets/fenbi32.ico // @defaulticon 粉笔网优化布局,清屏快速生成pdf // @match *.fenbi.com/* // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js // @grant GM_addStyle // @grant GM_getValue // @grant GM_setClipboard // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant unsafeWindow // @description 粉笔网优化布局,清屏快速生成pdf // @downloadURL https://update.greasyfork.icu/scripts/394310/%E7%B2%89%E7%AC%94%E7%BD%91%E5%88%B7%E9%A2%98%E5%AE%9D.user.js // @updateURL https://update.greasyfork.icu/scripts/394310/%E7%B2%89%E7%AC%94%E7%BD%91%E5%88%B7%E9%A2%98%E5%AE%9D.meta.js // ==/UserScript== (async function ($) { 'use strict'; const processCls = `__binyellow__processed__`; function processElements(selector, callback) { function checkForMatchingNode(nodes) { for (const node of nodes) { if (node.matches && node.matches(selector)) { callback(node); return true; } if (node.querySelectorAll) { const matchingDescendant = node.querySelector(selector); if (matchingDescendant) { callback($(matchingDescendant)); return true; } } } return false; } const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.type === "childList") { if (checkForMatchingNode(mutation.addedNodes)) { observer.disconnect(); break; } } } }); observer.observe(document.body, { childList: true, subtree: true }); } const mokao = () => { processElements(".exam-post-nav", (node) => { $(node).css({ left: 0, top: 0 }); const detailContent = $(".solution-detail.clear-float"); $(detailContent).css({ width: "100%" }); const optionsUl = $(detailContent).find(".options.ng-star-inserted"); $(optionsUl).css({ display: "flex", "justify-content": "space-between", "flex-wrap": "wrap" }); optionsUl.children().css("margin", "0"); $(detailContent).find(".exam-main-content.ng-tns-c3-0.ng-star-inserted").css({ width: "calc(100% - 302px)" }); $(".practice-header").hide(); $(detailContent).find(".solu-detail.ng-star-inserted").css({ margin: 0, padding: 0 }); $(detailContent).find(".nav-coll-divider.solu-divider").css({ margin: "6px 0" }); $(detailContent).find(".question-content > p:nth-child(2) > img").each(function() { var img = $(this); var width = img.width() || 0; var height = img.height() || 0; var newWidth = width * 0.6; var newHeight = height * 0.6; img.width(newWidth); img.height(newHeight); }); }); }; const caogao = () => { processElements(".draft-icon", () => { $(".draft-icon").on("click", function() { console.log("draft-icon 被点击"); $(document).on("keydown", function(event) { if (event.key === "Escape" || event.keyCode === 27) { $(".tool-item.exit").trigger("click"); $(document).off("keydown"); } }); }); }); }; var _GM_addStyle = /* @__PURE__ */ (() => typeof GM_addStyle != "undefined" ? GM_addStyle : void 0)(); var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)(); var _GM_setClipboard = /* @__PURE__ */ (() => typeof GM_setClipboard != "undefined" ? GM_setClipboard : void 0)(); var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)(); var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)(); var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)(); const customExamUrlsKey = "__custom-exam-urls-key__"; const customExamQuestionTypesKey = "__custom-exam-question-types-key__"; const customExamContentsKey = "__custom-exam-contents-key__"; const customExamMatchContent = "__custom-exam-match-content__"; const getLinks = async () => _GM_getValue(customExamUrlsKey, []); const setLinks = async (link) => { await _GM_setValue(customExamUrlsKey, link); }; const getOptions = async () => await _GM_getValue(customExamQuestionTypesKey); const setOptions = async (options) => { await _GM_setValue(customExamQuestionTypesKey, options); }; const setContents = async (content) => { try { const pre = await getContents(); await _GM_setValue(customExamContentsKey, [...pre, content]); } catch (error) { console.log(`setContent Error===>`, error); clearCustom(); } }; const getContents = async () => await _GM_getValue(customExamContentsKey); const getMatchContent = async () => await _GM_getValue(customExamMatchContent, ""); const setMatchContent = async (content) => { await _GM_setValue(customExamMatchContent, content); }; const clearCustom = async () => { await setLinks([]); await setOptions([]); await _GM_setValue(customExamContentsKey, []); await setMatchContent(""); await _GM_setValue(cacheExamNameFLag, false); await _GM_setValue(cacheExamName, void 0); await _GM_setValue(pdfExamNameArr, []); }; const xhrInterceptor = (rules, cb, resCb) => { const originalXHR = _unsafeWindow.XMLHttpRequest; _unsafeWindow.XMLHttpRequest = function() { const xhr = new originalXHR(); const originalOpen = xhr.open; xhr.open = function() { const method = arguments[0]; const url = arguments[1]; const matchedRule = rules.find((rule) => { if (typeof rule.url === "string") { return rule.url === url && (!rule.method || rule.method === method); } else if (rule.url instanceof RegExp) { return rule.url.test(url) && (!rule.method || rule.method === method); } else { return false; } }); if (matchedRule) { console.log("XHR request: " + method + " " + url); this._url = url; this._method = method; } originalOpen.apply(this, arguments); }; const originalSend = xhr.send; xhr.send = function() { const body = arguments[0]; if (this._url) { console.log(`send===>`, arguments, this._headers); this._body = body; console.log("XHR request body: " + body, this._url, this._headers); cb({ url: this._url, method: this._method, body: this._body, headers: this._headers }); } originalSend.apply(this, arguments); }; const originalSetRequestHeader = xhr.setRequestHeader; xhr.setRequestHeader = function(header, value) { if (this._url) { if (!this._headers) { this._headers = {}; } this._headers[header] = value; } originalSetRequestHeader.apply(this, arguments); }; const originalOnReadyStateChange = xhr.onreadystatechange; xhr.onreadystatechange = function() { if (this.readyState === 4 && this._url) { resCb == null ? void 0 : resCb({ url: this._url, method: this._method, body: this._body, headers: this._headers, status: this.status, statusText: this.statusText, responseText: this.responseText, response: JSON.parse(this.response), responseHeaders: this.getAllResponseHeaders() }); } originalOnReadyStateChange == null ? void 0 : originalOnReadyStateChange.apply(this, arguments); }; return xhr; }; }; const kuaiSuShuaTiKey = "__kuaiSuShuaTiKey__"; const cacheExamNameFLag = "__cache_exam_name_flag__"; const cacheExamName = "__cache_exam_name__"; const pdfExamNameArr = "__pdf_exam_name_arr__"; const setPdfNameArr = async (name) => { const preNameArr = await _GM_getValue(pdfExamNameArr, []); await _GM_setValue(pdfExamNameArr, [...preNameArr, name]); }; const getPdfNameArr = async () => { return await _GM_getValue(pdfExamNameArr, []); }; const genPdfName = async () => { var _a, _b; const nameArr = await getPdfNameArr(); let years = []; const gmOptions = await getOptions(); for (let i = 0; i < nameArr.length; i++) { let year = (_b = (_a = nameArr == null ? void 0 : nameArr[i]) == null ? void 0 : _a.match(/\d+/)) == null ? void 0 : _b[0]; years.push(year); } const optionAddon = gmOptions ? "-" + (gmOptions == null ? void 0 : gmOptions.join("-")) : ""; let result = years.join("-") + "年" + optionAddon; return result; }; const jiankong = async () => { jiankongKuaiSuLianXi(); await jianKongCustomName(); }; const jiankongKuaiSuLianXi = () => { const rules = [ { url: "https://tiku.fenbi.com/api/xingce/exercises?app=web&kav=100&av=100&hav=100&version=3.0.0.0", method: "POST" } ]; const callback = (config) => { _GM_setValue(kuaiSuShuaTiKey, config); }; xhrInterceptor(rules, callback); }; const jianKongCustomName = async () => { const flag = await _GM_getValue(cacheExamNameFLag); if (flag) { const rules = [ { url: new RegExp("https://tiku.fenbi.com/api/xingce/exercises/*"), method: "GET" } ]; const callback = (config) => { var _a, _b, _c, _d; const name = (_b = (_a = config == null ? void 0 : config.response) == null ? void 0 : _a.sheet) == null ? void 0 : _b.name; _GM_setValue(cacheExamName, (_d = (_c = config == null ? void 0 : config.response) == null ? void 0 : _c.sheet) == null ? void 0 : _d.name); setPdfNameArr(name); }; xhrInterceptor(rules, () => { }, callback); } }; const request = (props) => { const { body, ...rest } = props; return new Promise((resolve) => { _GM_xmlhttpRequest({ onload: (data) => { resolve(data); }, method: "POST", data: typeof body === "object" && !(body instanceof FormData) ? JSON.stringify(body) : body, ...rest }); }); }; const lianxiUrl = `https://www.fenbi.com/spa/tiku/exam/practice/xingce/xingce`; function shenlun() { const leftSubject = $(".zhenti-body-left.zhenti-body-part.bg-color-gray-light5"); leftSubject.find(".materials-container").css({ width: "100%", padding: 12 }); leftSubject.find(".material-content.ng-tns-c41-0").css({ width: "100%" }); leftSubject.find(".material-content.ng-tns-c41-0").find("#material").css({ width: "100%" }); const rightAnser = $(".zhenti-body-right.zhenti-body-part"); rightAnser.css({ flex: "none" }); rightAnser.find(".questions-container").css({ "padding-left": "12px" }); } const kuaisu = () => { processElements("main.exam-content", () => { const css = ` .solu-list-item.video-item fb-ng-solution-detail-item, .bg-color-gray-light2.border-gray-light3.font-color-gray-mid.expend-btn, .simple-nav-header.bg-color-gray-bold, .nav-coll-divider, .solu-answer-text.clear-float { display: none } main.exam-content { margin: 0 !important } .options.choice-options.font-color-gray-mid { display: flex } .solu-list.border-gray-light4 { margin-top: 0 } .solu-list-item.video-item { margin-bottom: 0 } .fb-collpase-bottom { width: calc(100% - 1024px); right: 0; } .fb-collpase-bottom.bg-color-gray-mid { margin: 0; width: 100% !important } .fixedActions.bg-color-gray-bold { right: 0 } `; _GM_addStyle(css); shenlun(); }); processElements(".fb-question-material", () => { $(".fb-question-material").css({ margin: 12 }); $(".material-content").css({ padding: 0 }); $(".ques-options-dry").css({ padding: 0 }); $(".options.font-color-gray-mid").css({ display: "flex", "flex-flow": "wrap" }); }); processElements(".solution-item.bg-color-gray-bold", (node) => { const solution = $(node).find(".solu-list.border-gray-light4"); $(solution).css({ padding: 8 }); $(solution).find("fb-ng-solution-detail-answer").hide(); }); processElements( ".solution-item.bg-color-gray-bold>app-fb-solution>fb-ng-solution > div[_ngcontent-fenbi-web-exams-c75] > div[_ngcontent-fenbi-web-exams-c75]", (node) => { node.css({ position: "absolute", right: 0 }); } ); processElements(".options.font-color-gray-mid", (node) => { node.css({ display: "flex", "flex-flow": "wrap", "justify-content": "space-between" }); }); processElements("app-report-header-test .exam-report", () => { $(".fixedActions.bg-color-gray-bold").removeClass(processCls); processElements(".fixedActions.bg-color-gray-bold", () => { var newButton = $(""); $(".fixedActions.bg-color-gray-bold").children().first().before(newButton); newButton.on("click", async function() { const requestConfig = await _GM_getValue(kuaiSuShuaTiKey, null); const data = await request(requestConfig); const { id } = JSON.parse(data == null ? void 0 : data.response); location.href = `${lianxiUrl}/${id}/2`; }); }); }); }; const dealWidth = () => { const cssRules = ` @media (max-width: 1000px) { .exam-content { width: calc(100% - 45px) !important; } #app-practice { min-width: 100% !important; } .tools-container { left: 0; } .fb-collpase-bottom { left: 0; width: 100% !important; } } @media (min-width: 1700px) { main.exam-content { width: 1600px !important; } aside.fb-collpase-bottom { width: calc(100% - 1600px) !important; } } .collapse-content { } .collapse-title { cursor: pointer; text-decoration: underline; color: blue; } .extra-dom { position: fixed; background-color: #fff; display: flex; flex-direction: column; gap: 6px; padding: 4px; box-sizing: content-box; } .extra-dom input[type=number] { width: 100%; } `; const styleTag = document.createElement("style"); styleTag.innerHTML = cssRules; document.head.appendChild(styleTag); }; function genQuestionTypes() { const options = []; $(".chapter-control-item").each(function() { const label = $(this).find(".font-color-gray-blod").text().slice(0, 2); const items = $(this).children("div").children().length; const rangeStart = options.length > 0 ? options[options.length - 1].range[1] + 1 : 1; const rangeEnd = rangeStart + items - 1; options.push({ label, range: [rangeStart, rangeEnd] }); }); return options; } const modalHtml = `