// ==UserScript==
// @name 粉笔网刷题宝
// @namespace http://tampermonkey.net/
// @version 0.0.47
// @author binyellow
// @icon https://nodestatic.fbstatic.cn/weblts_spa_online/page/assets/fenbi32.ico
// @defaulticon 粉笔网优化布局,清屏快速生成pdf
// @match https://www.fenbi.com/*
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @description 粉笔网优化布局,清屏快速生成pdf
// ==/UserScript==
(function ($) {
'use strict';
const processCls = `__binyellow__processed__`;
function processElements(selector, callback) {
const elements = $(`${selector}:not(.${processCls})`);
elements.each(function() {
callback($(this));
$(this).addClass(processCls);
});
}
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);
});
});
};
function observeDom(container, cbs2) {
function handleMutation(mutation) {
if (mutation.type === "childList") {
mutation.addedNodes.forEach((node) => {
cbs2.forEach((cb) => cb(node));
});
}
}
const observer = new MutationObserver((mutations) => {
mutations.forEach(handleMutation);
});
observer.observe(container, { childList: true, subtree: true });
}
const caogao = () => {
const caogao2 = $(".draft-icon");
if (caogao2 == null ? void 0 : caogao2.length) {
$(caogao2).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_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : 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)();
const xhrInterceptor = (rules, cb) => {
var originalXHR = window.XMLHttpRequest;
window.XMLHttpRequest = function() {
var xhr = new originalXHR();
var 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);
};
var 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);
};
return xhr;
};
};
const kuaiSuShuaTiKey = "__kuaiSuShuaTiKey__";
const jiankong = () => {
jiankongKuaiSuLianXi();
};
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 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 = (node, did2) => {
var _a;
const xingCeTiMu = $(node).find("main.exam-content");
if ((xingCeTiMu == null ? void 0 : xingCeTiMu.length) && !(did2 == null ? void 0 : did2.xingce)) {
did2.xingce = true;
const css = { margin: 0 };
$("main.exam-content").css(css);
$(".simple-nav-header.bg-color-gray-bold").hide();
const optionsCls = ".options.choice-options.font-color-gray-mid";
$(optionsCls).css({ display: "flex" });
$(".nav-coll-divider").hide();
$(".solu-list.border-gray-light4").css({ "margin-top": 0 });
$(".solu-answer-text.clear-float").hide();
$(".bg-color-gray-light2.border-gray-light3.font-color-gray-mid.expend-btn").hide();
$(".solu-list-item.video-item").css({ "margin-bottom": 0 });
$(".solu-list-item.video-item fb-ng-solution-detail-item").hide();
$("<style>.fb-collpase-bottom { width: calc(100% - 1024px); right: 0; }</style>").appendTo("head");
$(".fb-collpase-bottom.bg-color-gray-mid").css({ margin: 0, width: "100%" });
$(".fixedActions.bg-color-gray-bold").css({ right: 0 });
did2.xingce = false;
shenlun();
}
if (((_a = $(".fb-question-material")) == null ? void 0 : _a.length) && !did2.zhaiping) {
did2.zhaiping = true;
$(".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" });
}
const collections = $(".solution-item.bg-color-gray-bold");
if ((collections == null ? void 0 : collections.length) && !did2.collectionDid) {
collections.each(function() {
const solution = $(this).find(".solu-list.border-gray-light4");
$(solution).css({ padding: 8 });
$(solution).find("fb-ng-solution-detail-answer").hide();
});
did2.collectionDid = true;
}
const collectionBtn = $(
".solution-item.bg-color-gray-bold>app-fb-solution>fb-ng-solution > div[_ngcontent-fenbi-web-exams-c75] > div[_ngcontent-fenbi-web-exams-c75]"
);
if ((collectionBtn == null ? void 0 : collectionBtn.length) && !did2.collectionBtnDid) {
collectionBtn.each(function() {
$(this).css({ position: "absolute", right: 0 });
console.log(this);
});
did2.collectionBtnDid = true;
}
processElements(".options.font-color-gray-mid", (node2) => {
node2.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 = $("<button>重刷</button>");
$(".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);
};
const isExam = () => {
const { pathname } = location;
return pathname.slice(pathname.lastIndexOf("/") + 1) === "3";
};
const fixedActions = () => {
processElements(".fixedActions.bg-color-gray-bold", () => {
var newButton = $("<button>清屏</button>");
const marginLabel = '<label for="ti-jian-ju">题间距</label>';
var newInput = $('<input id="ti-jian-ju" type="number" value="180">');
const fontLabel = '<label for="zi-ti">字体</label>';
const fontInput = $('<input id="zi-ti" type="number" value="20">');
const $settingContainer = $(`<div class="collapse">
<a class="collapse-title">设置></a>
<div class="collapse-content">
</div>
</div>`);
$settingContainer.find(".collapse-content").append(marginLabel, newInput, fontLabel, fontInput);
const options = [
{ label: "常识", range: [1, 20] },
{ label: "言语", range: [21, 60] },
{ label: "数量", range: [61, 70] },
{ label: "判断", range: [71, 105] },
{ label: "资料", range: [106, 120] }
];
const $checkboxContainer = $(`<div class="collapse">
<a class="collapse-title">题型></a>
<div class="collapse-content">
</div>
</div>`);
options.forEach((option, index) => {
const isChecked = option.label !== "常识";
const $checkbox = $(`<input type="checkbox" id="option-${index}" ${isChecked ? "checked" : ""} />`);
const $label = $(`<label for="option-${index}">${option.label}</label>`);
$checkboxContainer.find(".collapse-content").append($checkbox, $label);
});
if (isExam()) {
$(".fixedActions.bg-color-gray-bold").children().first().before($checkboxContainer);
}
const fixedActions2 = $(".fixedActions.bg-color-gray-bold");
const position = fixedActions2.position();
const width = fixedActions2.outerWidth() || 0;
const extraDom = $("<div>", { class: "extra-dom" });
extraDom.css({
left: position.left - width - 15,
top: "10vh",
width: width + 6
});
extraDom.append(newButton, $settingContainer, $checkboxContainer);
$("body").append(extraDom);
$(".collapse-title").on("click", function() {
$(this).next(".collapse-content").slideToggle();
});
newButton.on("click", async function() {
if (isExam()) {
$(".exam-detail.bg-color-gray-bold > div").hide();
options.forEach((option, index) => {
const $checkbox = $(`#option-${index}`);
if ($checkbox.prop("checked")) {
const [start, end] = option.range;
for (let i = start - 1; i < end; i++) {
$(".exam-detail.bg-color-gray-bold > div").eq(i).show();
}
}
});
}
await scrollToNextImage();
var examContent = $("main.exam-content");
var inputValue = newInput.val();
var fontValue = fontInput.val();
$("body").empty();
$("body").append(examContent);
$("body").append(`<style>
.fixedActions.bg-color-gray-bold,.fb-collpase-bottom, app-side-tool,.fb-question > div:last-child[_ngcontent-fenbi-web-exams-c68],div[_ngcontent-fenbi-web-exams-c69] > div[_ngcontent-fenbi-web-exams-c69],.content.font-color-gray-mid>p.ques-type {
display: none;
}
.fb-question-options.fenbi-ng-utils > div[_ngcontent-fenbi-web-exams-c40],div.ques-options-dry {
padding: 16px 0 0 0;
margin-bottom: ${inputValue}px;
}
.options.font-color-gray-mid {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.options.font-color-gray-mid > li {
margin: 0 !important;
}
[_nghost-fenbi-web-exams-c40] p, [_nghost-fenbi-web-exams-c40] .options-material {
font-weight: normal;
font-size: ${fontValue}px;
}
main.exam-content {
margin-right: 35px !important;
}
.material-nav.bg-color-gray-light {
display: none;
}
</style>`);
$(".nav-coll-divider").hide();
$(".fb-question>div:last-child > button").hide();
});
});
};
function isImageLoaded(img) {
if (!img.complete) {
return false;
}
if (typeof img.naturalWidth !== "undefined" && img.naturalWidth === 0) {
return false;
}
return true;
}
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function scrollToNextImage() {
var _a, _b;
const images = $("#app-practice img").toArray().sort((a, b) => {
var _a2, _b2;
const aTop = ((_a2 = $(a).offset()) == null ? void 0 : _a2.top) ?? 0;
const bTop = ((_b2 = $(b).offset()) == null ? void 0 : _b2.top) ?? 0;
return aTop - bTop;
});
const filteredImages = images.filter((image, index) => {
var _a2, _b2;
if (index > 0) {
const prevImage = images[index - 1];
return (((_a2 = $(image).offset()) == null ? void 0 : _a2.top) ?? 0) !== (((_b2 = $(prevImage).offset()) == null ? void 0 : _b2.top) ?? 0);
}
return true;
});
const scrollContainer = $("#fenbi-web-exams");
for (const image of filteredImages) {
if (!isImageLoaded(image)) {
await new Promise((resolve) => {
$(image).on("load", function() {
resolve();
});
});
}
const imagePositionInContainer = (((_a = $(image).offset()) == null ? void 0 : _a.top) ?? 0) - (((_b = scrollContainer.offset()) == null ? void 0 : _b.top) ?? 0) + (scrollContainer.scrollTop() ?? 0);
await new Promise((resolve) => {
scrollContainer.animate(
{
scrollTop: imagePositionInContainer
},
50,
function() {
resolve();
}
);
});
await delay(50);
}
}
let did = {};
const cbs = [];
cbs.push((node) => kuaisu(node, did));
cbs.push(caogao);
cbs.push(mokao);
cbs.push(fixedActions);
const initCbs = [];
initCbs.push(dealWidth);
initCbs.push(() => {
});
initCbs.forEach((cb) => cb());
observeDom(document.body, cbs);
jiankong();
})($);