// ==UserScript== // @name 超星按题目的差异度排序 // @namespace http://tampermonkey.net/ // @version 2025-12-19-002 // @description 差异度越小的,排在前面。建议(1)当前页显示条目数设置为最大 (2)打开“显示题目详情”选项。 // @author 周利斌 // @match https://mooc2-ans.chaoxing.com/mooc2-ans/qbank/questionlist?courseid=* // @match https://mooc2-ans.chaoxing.com/mooc2-ans/exam/preFetchQFromExamQuestionBank?paperId=* // @icon https://www.google.com/s2/favicons?sz=64&domain=chaoxing.com // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== // https://greasyfork.org/zh-CN/scripts/532871-%E8%B6%85%E6%98%9F%E6%8C%89%E9%A2%98%E7%9B%AE%E7%9A%84%E5%B7%AE%E5%BC%82%E5%BA%A6%E6%8E%92%E5%BA%8F // 立即执行函数表达式,创建一个独立的作用域,防止全局变量污染 (async function () { "use strict"; console.log(111) const getValue = window.GM_getValue && typeof GM_getValue !== "undefined" ? GM_getValue : (key, value) => (localStorage.getItem(key) === null ? value : JSON.parse(localStorage.getItem(key))); const setValue = window.GM_setValue && typeof GM_setValue !== "undefined" ? GM_setValue : (key, value) => localStorage.setItem(key, JSON.stringify(value)); const sleep = (ms, val = true) => new Promise(r => setTimeout(() => r(val), ms)); const delay = (ms, call, ...args) => new Promise((r, j) => setTimeout(async () => { try { r(await (typeof call === 'function' ? call(...args) : call)) } catch (e) { j(e) } }, ms)); /** * Create (or return if exists) a floating control panel with optional font-size controls, * draggable handle, and a close button. Position and font-size are persisted by `id`. * * @param {Object} [options={}] - Panel options * @param {string} [options.id='_zlb_root_div_'] - Unique DOM id for the panel container * @param {boolean} [options.fontsize=true] - Whether to render font-size controls * @param {boolean} [options.drag=true] - Whether to render a draggable handle * @param {boolean|function} [options.close=true] - true to show a default close button; a function to run before removal * @param {keyof HTMLElementTagNameMap} [options.tagName='button'] - Tag name for interactive controls * @returns {HTMLDivElement} The panel DOM element */ function getPanel({ id = '_zlb_root_div_', fontsize = true, drag = true, close = true, tagName = 'button', parent = undefined } = {}) { const closeButtonId = id + '_close_'; const closeCallBack = [] const dragButtonId = id + '_drag_'; const font1ButtonId = id + '_font1_'; const font2ButtonId = id + '_font2_'; let panelElement = document.getElementById(id); function createCloseButton(host) { if (!close) return; if (typeof close === 'function') closeCallBack.push(close); if (host.querySelector("#" + closeButtonId)) return appendTo( { parent: host, id: closeButtonId }, tagName, 'X关闭X', () => { for (const ccb of closeCallBack) ccb() host.remove(); } ) } // Font-size controls function createFontButton(panelElement) { if (panelElement.querySelector("#" + font1ButtonId)) return; if (fontsize) { appendTo(panelElement, tagName, '-字号-', () => { currentFontSize = Math.max(6, currentFontSize * 0.9); setValue(id + ':fs', currentFontSize); updatePanelStyles(); }, font1ButtonId); appendTo(panelElement, tagName, '+字号+', () => { currentFontSize = currentFontSize * 1.1; setValue(id + ':fs', currentFontSize); updatePanelStyles(); }, font2ButtonId); } } // Drag handle function createDragButton(host) { if (!drag) return console.log(host) if (host.querySelector("#" + dragButtonId)) return; const dragHandleButton = appendTo(panelElement, tagName, '✥拖动✥', "", dragButtonId); dragHandleButton.addEventListener('mousedown', (event) => { const rect = panelElement.getBoundingClientRect(); const deltaX = event.clientX - rect.left; const deltaY = event.clientY - rect.top; const moveHandler = (moveEvent) => { panelElement.style.left = (moveEvent.clientX - deltaX) + 'px'; panelElement.style.top = (moveEvent.clientY - deltaY) + 'px'; }; const upHandler = () => { document.removeEventListener('mousemove', moveHandler); document.removeEventListener('mouseup', upHandler); const leftInPercent = (parseFloat(panelElement.style.left) / document.documentElement.clientWidth) * 100; const topInPercent = (parseFloat(panelElement.style.top) / document.documentElement.clientHeight) * 100; leftPercent = Math.min(Math.max(leftInPercent, 0), 95); topPercent = Math.min(Math.max(topInPercent, 0), 95); // Persist and reflect panelElement.style.left = leftPercent + '%'; panelElement.style.top = topPercent + '%'; setValue(id + ':L', leftPercent); setValue(id + ':T', topPercent); updatePanelStyles(); }; document.addEventListener('mousemove', moveHandler); document.addEventListener('mouseup', upHandler); }); } // If panel already exists, optionally add/refresh close button and return it. if (panelElement) { createCloseButton(panelElement); createDragButton(panelElement); createFontButton(panelElement); return /** @type {HTMLDivElement} */ (panelElement); } // Build panel container panelElement = document.createElement('div'); panelElement.id = id; panelElement.classList.add('notranslate'); panelElement.setAttribute('translate', 'no'); panelElement.onmousedown = panelElement.oncontextmenu = (event) => event.stopPropagation(); if (parent) { parent.appendChild(panelElement) } else document.body.appendChild(panelElement); // Persistent state let currentFontSize = Number(getValue(id + ':fs', 12)); let leftPercent = Math.min(Math.max(Number(getValue(id + ':L', 50)), 0), 95); let topPercent = Math.min(Math.max(Number(getValue(id + ':T', 50)), 0), 95); // Style element const styleElement = document.createElement('style'); panelElement.appendChild(styleElement); /** * Update the panel CSS rule (initial position, size, look). */ function updatePanelStyles() { console.log(currentFontSize) styleElement.textContent = `div#${id}{ position:fixed; z-index:999999; background-color:rgba(187, 180, 180, 0.9); border:1px solid rgba(191, 70, 173, 0.9); max-width:50vw; left:${leftPercent}%; top:${topPercent}%; user-select:none; font-size:${currentFontSize}px; display:flex; flex-wrap:wrap; } #${id} button{ border-radius:${currentFontSize}px; min-width:auto; display: inline-flex; padding:0 4px; font-size:${currentFontSize}px; } #${id} span{ margin:0 2px; font-size:${currentFontSize}px; } #${id} label{ margin:0px 2px; display: inline-flex; border:1px solid rgba(117,70,227,.7); border-radius:${currentFontSize}px; font-size:${currentFontSize}px; }`; } updatePanelStyles(); createDragButton(panelElement) createCloseButton(panelElement); createFontButton(panelElement) // Optional auto-clean if panel has no interactive children (only