您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
科举小抄 - 阿里云大学“科考”辅助工具
当前为
// ==UserScript== // @name 科举小抄 // @namespace https://github.com/fuckKeju/fuckKeju // @version 0.0.4 // @description 科举小抄 - 阿里云大学“科考”辅助工具 // @author fuckKeju // @match *.developer.aliyun.com/* // @run-at document-start // @grant unsafeWindow // ==/UserScript== /* 题库数据 */ var customQuestionsDatabase = [] var useCustomQuestionsDatabase = false var hasInit = false function fuckKeju () { if (hasInit) { return false } console.log('科举小抄 init suc') hasInit = true const subjectTitle = document.querySelector('.yq-main-examination .top-info h2.title-content').innerText const isExamMode = document.querySelector('.yq-main-examination .time-info') let questionsDatabase = [] try { questionsDatabase = JSON.parse(localStorage.getItem(subjectTitle) || '[]') } catch (e) { questionsDatabase = [] } /* 使用预置数据,而非定义的数据 */ if (useCustomQuestionsDatabase) { questionsDatabase = customQuestionsDatabase } var result = [] var items = document.querySelectorAll('.question-panel .question-item') if (items) { items.forEach(item => { const type = item.querySelector('.q-title .q-tag').innerText.trim() const title = item.querySelector('.q-title .q-t-text').innerText.trim().replace(/\s+/gi, ' ').replace(/\?{2,}/gi, ' ') const answerList = [] const answerListEl = item.querySelectorAll('.q-option .answer-text') console.log(answerListEl) answerListEl.forEach(answerEl => { let answer = answerEl.innerText.trim() const checkedEl = answerEl.parentNode.querySelector('input') if (checkedEl && checkedEl.checked) { answer += ' --checked' } answerList.push(answer) }) const data = { title, type, answerList } const pointEl = item.querySelector('.e-point .p-detail') if (pointEl) { data.point = '相关知识点:' + pointEl.innerText.trim() } else { data.point = '未匹配到任何相关知识点' } const rightAnswerEl = item.querySelector('.right-answer') if (rightAnswerEl) { data.rightAnswer = rightAnswerEl.innerText.trim() || '答案正确' } else { if (isExamMode) { data.rightAnswer = '答案未知' } else { data.rightAnswer = '答案正确' } } result.push(data) /* 判断当前题目是否已经存在 */ let hasInDatabase = false /* 提取相关问题 */ const titleTxt = title.replace(/^\d+\./, '') let relatedQuestions = [] function relatedQuestionsHandler (item) { const itemTitle = item.title.replace(/\s+/gi, ' ').replace(/\?{2,}/gi, ' ') if (itemTitle.includes(titleTxt)) { const answerA = answerList[0].replace(/^[ABCDEFG]\.\s/, '').replace(/\s+--checked/, '') for (let i = 0; i < item.answerList.length; i++) { const answerTxt = item.answerList[i] if (answerTxt.includes(answerA)) { relatedQuestions.push(item) break } } } if (itemTitle === title) { hasInDatabase = true } } questionsDatabase.forEach(list => { if (Array.isArray(list)) { list.forEach(item => { relatedQuestionsHandler(item) }) } else { relatedQuestionsHandler(list) } }) /* 查找是否存在答对的历史记录,优先显示答对的数据 */ if (relatedQuestions.length > 1) { const rightAnswerArr = [] const wrongAnswerArr = [] relatedQuestions.forEach(data => { if (data.rightAnswer === '答案正确') { rightAnswerArr.push(data) } else { wrongAnswerArr.push(data) } }) relatedQuestions = rightAnswerArr.concat(wrongAnswerArr) } /* 收集题目数据 */ if (!isExamMode && !hasInDatabase) { questionsDatabase.push(data) } const dd = document.createElement('dd') dd.setAttribute('class', 'relatedQuestions') dd.style.marginTop = '30px' dd.style.display = 'none' dd.style.border = '1px solid #ccc' dd.style.borderRadius = '5px' // dd.style.padding = '10px' // dd.style.backgroundColor = '#f9f9f9' if (item.querySelector('.relatedQuestions')) { item.removeChild(item.querySelector('.relatedQuestions')) } if (relatedQuestions.length) { const codeEl = document.createElement('pre') codeEl.style.border = 'none' codeEl.innerHTML = JSON.stringify(relatedQuestions, null, 2) dd.appendChild(codeEl) item.appendChild(dd) } else { dd.innerText = '暂无相关题目信息,先考几遍,然后查看考试结果再试试吧' item.appendChild(dd) } item.ondblclick = function (event) { const relatedQuestions = item.querySelector('.relatedQuestions') if (relatedQuestions) { if (relatedQuestions.style.display === 'none') { relatedQuestions.style.display = 'block' relatedQuestions.style.opacity = 0.4 relatedQuestions.style.overflow = 'auto' relatedQuestions.style.maxHeight = '200px' } else { relatedQuestions.style.display = 'none' } } } }) } localStorage.setItem(subjectTitle, JSON.stringify(questionsDatabase)) /* 切换题目时候,隐藏小抄 */ const switchDoms = document.querySelectorAll('.question-num span.item') const switchDoms02 = document.querySelectorAll('.e-opt-panel a') function hideRelatedQuestions () { const relatedQuestionsEls = document.querySelectorAll('.relatedQuestions') relatedQuestionsEls.forEach(item => { item.style.display = 'none' }) } switchDoms.forEach(el => { el.onmouseenter = hideRelatedQuestions }) switchDoms02.forEach(el => { el.onclick = hideRelatedQuestions }) console.log(JSON.stringify(result, null, 2)) } function ready (selector, fn, shadowRoot) { const listeners = [] const win = window const doc = shadowRoot || win.document const MutationObserver = win.MutationObserver || win.WebKitMutationObserver let observer function $ready (selector, fn) { // 储存选择器和回调函数 listeners.push({ selector: selector, fn: fn }) if (!observer) { // 监听document变化 observer = new MutationObserver(check) observer.observe(shadowRoot || doc.documentElement, { childList: true, subtree: true }) } // 检查该节点是否已经在DOM中 check() } function check () { for (let i = 0; i < listeners.length; i++) { var listener = listeners[i] var elements = doc.querySelectorAll(listener.selector) for (let j = 0; j < elements.length; j++) { var element = elements[j] if (!element._isMutationReady_) { element._isMutationReady_ = true listener.fn.call(element, element) } } } } $ready(selector, fn) } ready('.question-panel .question-item', () => { /** * 此处必须延迟执行,题目渲染和选中渲染是异步操作 * 需要延时等待选中的渲染成功才执行初始化逻辑 */ console.log('检查到进入了试题页面,即将为你初始化小炒逻辑') setTimeout(function () { fuckKeju() }, 1000 * 3) })