您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案,能够跳过秒看教学视频
当前为
// ==UserScript== // @name 宜宾智慧校园助手 // @namespace 智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案===来自计算机科学与技术学院--修改自若离智慧校园 // @version 6.5 // @description 智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案,能够跳过秒看教学视频 // @author 计算机科学与技术学院---软工 // @match https://mooc.yibinu.edu.cn/* // @icon https://pic.imgdb.cn/item/673c85b1d29ded1a8ce8b97c.png // @resource cs1 https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/ant-design-vue/1.7.8/antd.css // @resource cs2 https://pan.ruoli.cc/s/8b0cc4 // @require https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js // @require https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/ant-design-vue/1.7.8/antd.min.js // @require https://cdn.sheetjs.com/xlsx-0.19.3/package/dist/xlsx.full.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js // @run-at document-end // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_getResourceText // ==/UserScript== // 脚本初始化 var setting = { 'logs': ['初始化脚本完成,', '当前脚本版本:V6.5'], 'datas': [], 'secretKey': '你好', // 暗号 '_vt': '274c8b3f2a8c63ffc960dd1e4e3f0eac', }; // 时间值 function decryptValidDuration() { try { const validDurations = { 'c51ce410c124a10e0db5e4b97fc2af39': 86400000, '274c8b3f2a8c63ffc960dd1e4e3f0eac': 172800000, 'e2ef524fbf3d9fe611d5a8e90fefdc9c': 259200000, '069059b7ef840f0c74a814ec9237b6ec': 432000000, '7f6ffaa6bb0b408017b62254211691b5': 604800000, '149e9677a5989fd342ae44213df68868': 2592000000 }; return validDurations[setting._vt] || 172800000; // 默认返回2天 } catch (e) { console.error('解密时间值出错:', e); return 172800000; // 解密出错时返回默认值(2天) } } // 简化的验证时间管理 function setValidTime() { try { const validDuration = decryptValidDuration(); const validUntil = Date.now() + validDuration; const data = { time: validUntil, hash: CryptoJS.SHA256(validUntil.toString()).toString() }; localStorage.setItem('scriptValidUntil', JSON.stringify(data)); return true; } catch (e) { console.error('设置验证时间出错:', e); return false; } } // 检查验证时间 function checkValidTime() { try { const data = localStorage.getItem('scriptValidUntil'); if (!data) return false; const { time, hash } = JSON.parse(data); const now = Date.now(); // 验证时间和哈希 if (time && hash && hash === CryptoJS.SHA256(time.toString()).toString() && time > now) { return true; } localStorage.removeItem('scriptValidUntil'); return false; } catch (e) { console.error('检查验证时间出错:', e); localStorage.removeItem('scriptValidUntil'); return false; } } // 将验证函数定义为全局函数 window.verifySecret = function() { const input = document.getElementById('secretInput'); if (!input) { console.error('找不到输入框元素'); return; } const inputValue = input.value.trim(); if (!inputValue) { input.style.borderColor = '#ff4d4f'; input.style.animation = 'shake 0.5s'; setTimeout(() => { input.style.borderColor = '#e8e8e8'; input.style.animation = ''; }, 1000); return; } if (inputValue !== setting.secretKey) { const modalDiv = document.querySelector('#secretModal > div'); if (modalDiv) { modalDiv.style.animation = 'shake 0.5s'; input.style.borderColor = '#ff4d4f'; setTimeout(() => { modalDiv.style.animation = ''; input.style.borderColor = '#e8e8e8'; }, 1000); } return; } try { // 设置验证时间 if (!setValidTime()) { throw new Error('设置验证时间失败'); } // 添加关闭动画 const modal = document.getElementById('secretModal'); if (modal) { modal.style.animation = 'modalFadeOut 0.3s ease'; setTimeout(() => { modal.remove(); continueInit(); // 添加成功提示 if (window.vue) { window.vue.$message.success('验证成功!'); } }, 300); } } catch (error) { console.error('验证过程出错:', error); if (window.vue) { window.vue.$message.error('验证过程出错,请刷新页面重试'); } } }; // 添加键盘事件监听器的函数 function addKeyboardListener() { document.addEventListener('keydown', function(event) { if (event.key === 'Enter') { const secretInput = document.getElementById('secretInput'); if (secretInput && document.activeElement === secretInput) { verifySecret(); } } }); } // 日志 function log(logText){ setting.logs.unshift(logText); // Ensure Vue instance logs are updated if (window.vue) { window.vue.$nextTick(() => { window.vue.logs = [...setting.logs]; }); } } // 添加一个清理HTML标签的函数 function cleanHtmlTags(text) { if (!text) return ''; // 将HTML转换为纯文本 let temp = document.createElement('div'); temp.innerHTML = text; let cleanText = temp.textContent || temp.innerText; // 清理多余的空白字符 cleanText = cleanText.replace(/\s+/g, ' ').trim(); return cleanText; } // 从后台获取答案 function getAnswer(url, data){ log('正在获取答案...'); let id = url.match(/\/examSubmit\/(\d+)\/getExamPaper/)[1]; GM_xmlhttpRequest({ method: "post", url: url, data: data, dataType: 'json', headers: { 'Origin': location.origin, 'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36', 'Content-type': 'application/x-www-form-urlencoded;charset=utf-8', 'Referer': `https://mooc.yibinu.edu.cn/examTest/stuExamList/${id}.mooc` }, onload: function(res){ if(res.status == 200){ try { let response = JSON.parse(res.responseText); if (response && response.paper && response.paper.paperStruct) { log("获取答案成功正在格式化答案!"); formatAnswer(response.paper.paperStruct); } else { log("答案数据格式异常,请检查接口返回"); } } catch (error) { log("解析答案数据失败:" + error.message); } } else { log("获取答案失败,状态码:" + res.status); } }, onerror: function(error) { log("求答案失败:" + error.message); } }); } //格式化答案 function formatAnswer(str) { try { setting.datas = []; // 清空之前的数据 if (!Array.isArray(str)) { log("答案数据式错误"); return; } str.forEach((listItem, index) => { if (!listItem.quiz) { return; } // 使用cleanHtmlTags清理题目内容 var question = cleanHtmlTags(listItem.quiz.quizContent) || "未知题目"; var options = {}; var optionContents = {}; // 存储选项内容 var answer = []; const questionNum = (index + 1).toString(); // 处理选择题 if (listItem.quiz.quizOptionses && listItem.quiz.quizOptionses.length > 0) { listItem.quiz.quizOptionses.forEach((optionItem, idx) => { if (optionItem && optionItem.optionId !== undefined) { const optionLabel = String.fromCharCode(65 + idx); options[optionItem.optionId] = optionLabel; optionContents[optionItem.optionId] = optionItem.optionContent || ''; } }); // 处理答案 if (listItem.quiz.quizResponses) { listItem.quiz.quizResponses.forEach(answerItem => { if (answerItem && options[answerItem.optionId]) { const label = options[answerItem.optionId]; const content = optionContents[answerItem.optionId]; answer.push(`${label}.${content}`); } }); } // 并序号和选项标签 const answerLabels = listItem.quiz.quizResponses .map(item => options[item.optionId]) .join(''); const idAndOptions = `${questionNum}.${answerLabels}`; setting.datas.push({ 'key': index.toString(), 'idAndOptions': idAndOptions, 'question': question, 'answer': answer.join('\n') // 每个选项答案换行显示 }); } else { // 处理填空题 if (listItem.quiz.quizResponses) { const fillAnswers = []; listItem.quiz.quizResponses.forEach(answerItem => { if (answerItem && answerItem.responseContent) { fillAnswers.push(answerItem.responseContent); } }); setting.datas.push({ 'key': index.toString(), 'idAndOptions': `${questionNum}.(填空)`, 'question': question, 'answer': fillAnswers.join('\n') // 多个填空答案换行显示 }); } } }); // 更新 Vue 实例中的数据 if (window.vue) { Vue.nextTick(() => { window.vue.answerList = [...setting.datas]; window.vue.hasAnswer = true; // 设置答案获取状态为 true }); } log(`成功处理 ${setting.datas.length} 道题目`); log('答案获取完成,可以切换到答案列表查看'); } catch (error) { log("格式化答案时出错:" + error.message); if (window.vue) { window.vue.hasAnswer = false; } } } //初始化界面 function initView(){ // 检查验证是否有效 if (checkValidTime()) { // 验证仍然有效,直接继续初始化 continueInit(); return; } // 创建验证界面的HTML const createModal = () => { const modalHtml = ` <div id="secretModal" style=" position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 10000; "> <div style=" background: white; padding: 30px; border-radius: 15px; box-shadow: 0 8px 24px rgba(0,0,0,0.2); width: 320px; text-align: center; animation: modalFadeIn 0.3s ease; "> <img src="https://pic.imgdb.cn/item/673c85b1d29ded1a8ce8b97c.png" style=" width: 64px; height: 64px; margin-bottom: 15px; "> <h2 style=" margin: 0 0 20px 0; color: #333; font-size: 20px; font-weight: 500; ">请输入暗号---你好</h2> <input type="text" id="secretInput" style=" width: 100%; padding: 12px; margin-bottom: 15px; border: 2px solid #e8e8e8; border-radius: 8px; font-size: 16px; outline: none; transition: all 0.3s; box-sizing: border-box; " placeholder="请输入暗号..."> <button id="verifyButton" style=" width: 100%; padding: 12px; border: none; background-color: #1890ff; color: white; border-radius: 8px; font-size: 16px; cursor: pointer; transition: all 0.3s; box-sizing: border-box; ">验证</button> </div> </div> `; document.body.insertAdjacentHTML('beforeend', modalHtml); // 添加事件监听器 const button = document.getElementById('verifyButton'); if (button) { button.addEventListener('click', window.verifySecret); } // 添加键盘事件监听 addKeyboardListener(); // 自动聚焦输入框 setTimeout(() => { const input = document.getElementById('secretInput'); if (input) { input.focus(); } }, 100); }; // 添加动画样式 const style = document.createElement('style'); style.textContent = ` @keyframes shake { 0%, 100% { transform: translateX(0); } 10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); } 20%, 40%, 60%, 80% { transform: translateX(5px); } } @keyframes modalFadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } @keyframes modalFadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-20px); } } `; document.head.appendChild(style); createModal(); } // 将原来的初始化代码移动到新的函数中 function continueInit() { var $div =$('<div class="rlBox minimized">' + ' <a-card title="宜宾学院智慧校园助手" style="width: 100%;height: 100%;">' + ' <template slot="extra">' + ' <span v-show="!close" style="margin-right: 10px; font-size: 12px; color: #999;">{{validTimeRemaining}}</span>' + ' <a-button :type="buttonColor" shape="circle" :icon="buttonIcon" @click="toClose" size="small"/>' + ' </template>' + ' <div style="margin-bottom: 15px;" v-show="!close">' + ' <a-button-group style="width: 100%;">' + ' <a-button type="danger" style="width: 25%;" @click="passVideo()">秒过视频</a-button>' + ' <a-button type="primary" style="width: 25%;" @click="exportExcel()">导出题库</a-button>' + ' <a-button type="success" style="width: 25%;" @click="clearLogs()">清除日志</a-button>' + ' <a-button type="warning" style="width: 25%;" @click="autoAnswer()">自动答题</a-button>' + ' </a-button-group>' + ' </div>' + ' <a-tabs default-active-key="1" @change="callback" v-show="!close">' + ' <a-tab-pane key="1" tab="运行日志">' + ' <div class="rl-panel log">' + ' <p v-for="item in logs" class="log_content">' + ' {{item}}' + ' </p>' + ' </div>' + ' </a-tab-pane>' + ' <a-tab-pane key="2" :tab="answerTabTitle" :disabled="!hasAnswer">' + ' <div class="rl-panel">' + ' <a-table id="rlTable"' + ' :pagination="false" bordered size="small" :columns="columns" :data-source="answerList">' + ' </a-table>' + ' </div>' + ' </a-tab-pane>' + ' </a-tabs>' + ' </a-card>' + '</div>'); // 更新样式 const customStyle = ` .rlBox { position: fixed; top: 10px; right: 10px; width: 400px; z-index: 9999; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); padding: 10px; transition: all 0.3s ease; transform: none !important; overflow: hidden; } /* 优化最小化状态 */ .rlBox.minimized { width: 40px !important; height: 40px !important; padding: 0 !important; overflow: hidden; opacity: 0.8; cursor: pointer; border-radius: 50%; background: #1890ff; box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } /* 按钮样式优化 */ .ant-btn-danger { background: #ff4d4f !important; border-color: #ff4d4f !important; color: white !important; } .ant-btn-danger:hover { background: #ff7875 !important; border-color: #ff7875 !important; } .ant-btn-primary { background: #1890ff !important; border-color: #1890ff !important; } .ant-btn-primary:hover { background: #40a9ff !important; border-color: #40a9ff !important; } .ant-btn-success { background: #52c41a !important; border-color: #52c41a !important; color: white !important; } .ant-btn-success:hover { background: #73d13d !important; border-color: #73d13d !important; } /* 最小化状态下的卡片样式 */ .rlBox.minimized .ant-card { background: transparent; border: none; box-shadow: none; } /* 最小化状态下的标题隐藏 */ .rlBox.minimized .ant-card-head-title { display: none; } /* 最小化状态下的开按钮样式 */ .rlBox.minimized .ant-btn-circle { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: transparent !important; border: 2px solid white !important; color: white !important; box-shadow: none; } .rlBox.minimized .ant-btn-circle:hover { background: rgba(255, 255, 255, 0.2) !important; } /* 最小化状态悬停效果 */ .rlBox.minimized:hover { opacity: 1; box-shadow: 0 6px 16px rgba(24, 144, 255, 0.4); transform: translateY(-2px) !important; } /* 移动端适配 */ @media screen and (max-width: 768px) { .rlBox { width: 300px; } .rlBox.minimized { width: 36px !important; height: 36px !important; } } /* 表格容器样式 */ .rl-panel { height: auto; max-height: calc(100vh - 250px); overflow-y: auto; overflow-x: hidden; } /* 表格样式优化 */ .ant-table-wrapper { overflow: visible; } .ant-table { min-width: 100%; background: transparent; } /* 美化滚动条样式 */ .rl-panel::-webkit-scrollbar { width: 6px; height: 6px; } .rl-panel::-webkit-scrollbar-thumb { background: #d9d9d9; border-radius: 3px; } .rl-panel::-webkit-scrollbar-track { background: #f0f0f0; border-radius: 3px; } /* 表格单元格样式 */ .ant-table-tbody > tr > td { white-space: normal; word-break: break-word; padding: 8px 16px; line-height: 1.5; max-width: 0; } /* 表格头部样式 */ .ant-table-thead > tr > th { background: #f5f5f5; padding: 12px 16px; white-space: nowrap; position: sticky; top: 0; z-index: 2; } /* 保表格布局合理 */ #rlTable { table-layout: fixed; width: 100%; } /* 移动端适配 */ @media screen and (max-width: 768px) { .rl-panel { max-height: calc(100vh - 200px); } .ant-table-tbody > tr > td { padding: 6px 12px; } .ant-table-thead > tr > th { padding: 8px 12px; } } `; $("body").append($div); GM_addStyle(GM_getResourceText("cs1")); GM_addStyle(GM_getResourceText("cs2")); GM_addStyle(customStyle); var vue = new Vue({ el: '.rlBox', data:{ logs: setting.logs, close: true, key: '1', columns:[ { title: '序号.选项', dataIndex: 'idAndOptions', key: 'idAndOptions', width: '80px', fixed: 'left', align: 'center' }, { title: '题目', dataIndex: 'question', key: 'question', width: '45%', ellipsis: true }, { title: '答案', dataIndex: 'answer', key: 'answer', width: '45%', customRender: (text) => { return text ? text.split('\n').join('<br/>') : ''; } } ], answerList: [], // 初化为空数组 isDragging: false, currentX: 0, currentY: 0, initialX: 0, initialY: 0, xOffset: 0, yOffset: 0, hasAnswer: false, // 添加答案获取状态标志 validUntil: localStorage.getItem('scriptValidUntil') || null, }, mounted() { window.vue = this; this.initDragEvents(); // 修改初始化位置设置 const box = document.querySelector('.rlBox'); box.style.right = '0px'; box.style.left = 'auto'; box.setAttribute('data-expand-side', 'right'); // 设置默认展开方向 // 添加窗口大小改变监听 window.addEventListener('resize', this.checkPosition); // 每分钟更新一次验证时间显示 setInterval(() => { this.validUntil = localStorage.getItem('scriptValidUntil'); }, 60000); }, computed:{ isShow(){ return this.close ? 0.8 : 1.0; }, buttonIcon(){ return this.close ? 'plus' : 'minus'; }, buttonColor(){ return this.close ? 'primary' : 'default'; }, answerTabTitle() { return this.hasAnswer ? '答案列表' : '答案列表 (等待获取...)'; }, validTimeRemaining() { const validTime = getValidTime(); if (!validTime) return '未验证'; const remaining = validTime - Date.now(); if (remaining <= 0) return '验证已过期'; const days = Math.floor(remaining / (24 * 60 * 60 * 1000)); const hours = Math.floor((remaining % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000)); return `验证剩余: ${days}天${hours}小时`; } }, methods: { callback(key) { if (key === '2' && !this.hasAnswer) { this.$message.warning('请等待答案获取完成后再查看答案列表'); this.key = '1'; // 保持在日志页面 return; } this.key = key; }, toClose() { this.close = !this.close; const box = document.querySelector('.rlBox'); const rect = box.getBoundingClientRect(); const windowWidth = window.innerWidth; if (this.close) { // 最小化时,判断靠近哪边 box.style.transition = 'all 0.3s ease'; const centerX = rect.left + rect.width / 2; if (centerX > windowWidth / 2) { // 靠右 box.style.right = '10px'; box.style.left = 'auto'; box.setAttribute('data-side', 'right'); } else { // 靠左 box.style.left = '10px'; box.style.right = 'auto'; box.setAttribute('data-side', 'left'); } box.classList.add('minimized'); } else { // 展开时 box.style.transition = 'all 0.3s ease'; box.classList.remove('minimized'); const side = box.getAttribute('data-side') || 'right'; if (side === 'right') { box.style.right = '10px'; box.style.left = 'auto'; } else { box.style.left = '10px'; box.style.right = 'auto'; } } }, passVideo() { let video = document.getElementsByTagName("video"); if(video.length == 0){ log("当前页面不存在视频,请确保视频已加载"); return; } let currentVideo = video[0]; // 移除之前的事件监听器(如果存在) currentVideo.removeEventListener('ended', this.handleNextVideo); // 添加新的视频结束监听器 currentVideo.addEventListener('ended', () => { log("视频播放完成,准备切换到下一个视频..."); this.handleNextVideo(); }); try { // 设置视频结束前的最后一秒 if (currentVideo.duration && !isNaN(currentVideo.duration)) { currentVideo.currentTime = currentVideo.duration - 0.1; currentVideo.playbackRate = 1; log("正在完成当前视频..."); } else { log("无法获取视频时长,请等待视频加载完成"); // 等待视频加载完成 currentVideo.addEventListener('loadedmetadata', () => { currentVideo.currentTime = currentVideo.duration - 0.1; currentVideo.playbackRate = 1; log("视频加载完成,正在处理..."); }); } } catch (error) { log("处理视频时出错:" + error.message); } }, exportExcel(){ // 检查是否有答案数据 if (!this.answerList || this.answerList.length === 0) { this.$message.error('没有可导出的答案数!请等待答案获取完成。'); log('导出失败:没有答案数据'); return; } // 准备数据 const data = this.answerList.map(item => ({ '序号.选项': item.idAndOptions, '题目': item.question, '答案': item.answer })); // 创建工作簿 const wb = XLSX.utils.book_new(); // 创建工作表 const ws = XLSX.utils.json_to_sheet(data); // 设置列宽 const colWidths = { '序号.选项': 10, '题目': 50, '答案': 30 }; ws['!cols'] = Object.keys(colWidths).map(key => ({ wch: colWidths[key] })); // 将工作表添加到工作簿 XLSX.utils.book_append_sheet(wb, ws, "题库"); // 生成并下载文件 XLSX.writeFile(wb, "题库.xlsx"); log('题库已导出为 Excel 文件'); }, clearLogs() { // 清空所有现有日志 this.logs = []; setting.logs = []; // 添加清除提示 const clearMessage = [ '日志已清除', '------------------------', ]; // 直接设置新的日志数组,而不是使用 log 函数 this.logs = clearMessage; setting.logs = [...clearMessage]; // 阻止其他日志添加 setTimeout(() => { // 确保清除状态保持 if (this.logs.length > clearMessage.length) { this.logs = [...clearMessage]; setting.logs = [...clearMessage]; } }, 200); }, // 优化拖动处理 initDragEvents() { const box = document.querySelector('.rlBox'); const dragZone = document.querySelector('.ant-card-head'); let startX, startY, initialMouseX, initialMouseY; dragZone.addEventListener('mousedown', (e) => { if (this.close) return; // 小化时禁止拖动 e.preventDefault(); this.isDragging = true; const rect = box.getBoundingClientRect(); startX = rect.left; startY = rect.top; initialMouseX = e.clientX; initialMouseY = e.clientY; box.style.transition = 'none'; document.body.style.userSelect = 'none'; }); document.addEventListener('mousemove', (e) => { if (!this.isDragging) return; const dx = e.clientX - initialMouseX; const dy = e.clientY - initialMouseY; let newX = startX + dx; let newY = startY + dy; box.style.left = `${newX}px`; box.style.top = `${newY}px`; box.style.right = 'auto'; // 实时检查位置 this.checkPosition(); }); document.addEventListener('mouseup', () => { if (this.isDragging) { this.isDragging = false; box.style.transition = 'all 0.2s'; document.body.style.userSelect = ''; } }); // 添加摸支持 dragZone.addEventListener('touchstart', (e) => { const touch = e.touches[0]; const rect = box.getBoundingClientRect(); startX = rect.left; startY = rect.top; initialMouseX = touch.clientX; initialMouseY = touch.clientY; this.isDragging = true; }); document.addEventListener('touchmove', (e) => { if (!this.isDragging) return; e.preventDefault(); const touch = e.touches[0]; const dx = touch.clientX - initialMouseX; const dy = touch.clientY - initialMouseY; let newX = startX + dx; let newY = startY + dy; const maxX = window.innerWidth - box.offsetWidth; const maxY = window.innerHeight - box.offsetHeight; newX = Math.min(Math.max(0, newX), maxX); newY = Math.min(Math.max(0, newY), maxY); box.style.left = `${newX}px`; box.style.top = `${newY}px`; }); document.addEventListener('touchend', () => { this.isDragging = false; }); }, handleNextVideo() { // 获取所有视频列表项 const videoItems = document.querySelectorAll('li[title*="mp4"]'); if (!videoItems || videoItems.length === 0) { log("未找到视频列表"); return; } // 找到当前激活的视频 const currentVideoItem = Array.from(videoItems).find(item => item.classList.contains('tab-active') || item.querySelector('.tab-inner.current') ); if (!currentVideoItem) { log("无法确定当前视频位置"); return; } // 判断是否是最后一个视频 const isLastVideo = currentVideoItem === videoItems[videoItems.length - 1]; if (isLastVideo) { log("当前已是最后一个视频"); return; } // 查找"开始下一条目"按钮 const nextButton = document.querySelector('.view-tip[itemid="1"]'); if (!nextButton) { log("未找到一个视频按钮"); return; } // 点击"开始下一条目"按钮 log("正在切换到下一个视频..."); nextButton.click(); // 等待新视频加载 let attempts = 0; const maxAttempts = 10; const checkInterval = setInterval(() => { const newVideo = document.getElementsByTagName("video")[0]; if (newVideo && newVideo.readyState >= 2) { // 确保视频已经加载足够的数据 clearInterval(checkInterval); log("新视频加载成功,准备播放"); setTimeout(() => { this.passVideo(); }, 1500); // 增加延迟以确保视频完全加载 } else { attempts++; if (attempts >= maxAttempts) { clearInterval(checkInterval); log("新视频加载超时,请手动切换"); } } }, 1000); }, checkPosition() { const box = document.querySelector('.rlBox'); const rect = box.getBoundingClientRect(); const windowWidth = window.innerWidth; const windowHeight = window.innerHeight; // 检查并修正水平位置 if (rect.right > windowWidth) { box.style.right = '0px'; box.style.left = 'auto'; } if (rect.left < 0) { box.style.left = '0px'; box.style.right = 'auto'; } // 检查并修正垂直位置 if (rect.bottom > windowHeight) { box.style.top = `${windowHeight - rect.height - 10}px`; } if (rect.top < 0) { box.style.top = '10px'; } }, autoAnswer() { log("开始自动答题..."); // 检查是否已获取答案 if (!setting.datas || setting.datas.length === 0) { log("未找到答案信息,请先获取答案"); return; } log(`共发现 ${setting.datas.length} 道题目的答案`); let answeredCount = 0; // 遍历答案列表 setting.datas.forEach((answerData, index) => { try { // 获取当前题目的答案 const answer = answerData.answer; if (!answer) { log(`第 ${index + 1} 题答案为空`); return; } // 获取题目容器 const questionContainer = document.querySelector(`.view-test[data-num="${index + 1}"]`) || document.querySelector(`.view-test:nth-child(${index + 1})`); if (!questionContainer) { log(`第 ${index + 1} 题未找到题目容器`); return; } // 判断题目类型 const isMultiChoice = questionContainer.querySelector('.input-c') !== null; const isSingleChoice = questionContainer.querySelector('.input-r') !== null; const isFillBlank = questionContainer.querySelector('.fillblank') !== null; if (isMultiChoice || isSingleChoice) { // 处理选择题 const answerLetters = answer.split('\n').map(a => a.trim().charAt(0)); const options = questionContainer.querySelectorAll('.t-option'); options.forEach((option, idx) => { const letter = String.fromCharCode(65 + idx); if (answerLetters.includes(letter)) { // 查找选项的点击元素 const clickTarget = option.querySelector('a[href="javascript:void(0)"]') || option.querySelector(isMultiChoice ? '.input-c' : '.input-r'); if (clickTarget) { // 检查是否已经选中 const isChecked = option.querySelector(isMultiChoice ? '.input-c.selected' : '.input-r.selected'); if (!isChecked) { clickTarget.click(); log(`第 ${index + 1} 题选择了选项 ${letter}`); } } } }); answeredCount++; } else if (isFillBlank) { // 处理填空题 const fillBlanks = questionContainer.querySelectorAll('.fillblank'); const answers = answer.split('\n').map(a => a.replace(/^.*?\./, '').trim()); // 如果有多个填空框 if (fillBlanks.length > 1) { fillBlanks.forEach((input, idx) => { if (answers[idx]) { input.value = answers[idx]; // 触发必要的事件 input.dispatchEvent(new Event('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); log(`第 ${index + 1} 题第 ${idx + 1} 个空填写了答案: ${answers[idx]}`); } }); } else if (fillBlanks.length === 1) { // 单个填空框 const input = fillBlanks[0]; input.value = answers[0]; // 触发必要的事件 input.dispatchEvent(new Event('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); log(`第 ${index + 1} 题填写了答案: ${answers[0]}`); } answeredCount++; } } catch (error) { log(`第 ${index + 1} 题自动答题出错: ${error.message}`); } }); // 显示完成提示 log(`自动答题完成!成功答题 ${answeredCount} 道题目`); this.$message.success(`自动答题完成!成功答题 ${answeredCount} 道题目,请检查后手动提交。`); } } }); } // 初始化获取答案,延迟5秒防止流程崩溃 function initGetAnswer(settings){ var url = location.origin + settings.url; var data = settings.data.replace(/(testPaperId=).*?(&)/,'$1' + '1250' + '$2'); console.log("=====") console.log(url,'url') console.log(data) getAnswer(url,data); } // 自动答题功能 function autoAnswerQuestions() { log("开始自动答题..."); // 获取所有题目 const questions = document.querySelectorAll('.view-test'); if(!questions || questions.length === 0) { log("未找到题目,请确认是否在答题页面"); return; } log(`共发现 ${questions.length} 道题目`); questions.forEach((question, index) => { // 获取题目类型 const isMultiChoice = question.querySelector('.t-option .input-c') !== null; // 多选 const isSingleChoice = question.querySelector('.t-option .input-r') !== null; // 单选 const isFillBlank = question.querySelector('.fill_b .fillblank') !== null; // 填空 // 获取正确答案 const answerElem = question.querySelector('.test-ana[_type="response"]'); if(!answerElem) { log(`第 ${index + 1} 题未找到答案信息`); return; } const answerText = answerElem.textContent.replace('参考答案:','').trim(); // 根据题型选择答案 if(isMultiChoice) { // 多选题 const answers = answerText.split(' '); answers.forEach(answer => { const options = question.querySelectorAll('.t-option'); options.forEach((option, idx) => { if(answer === String.fromCharCode(65 + idx)) { const checkbox = option.querySelector('.input-c'); if(checkbox && !checkbox.classList.contains('selected')) { checkbox.click(); } } }); }); } else if(isSingleChoice) { // 单选题 const options = question.querySelectorAll('.t-option'); options.forEach((option, idx) => { if(answerText === String.fromCharCode(65 + idx)) { const radio = option.querySelector('.input-r'); if(radio && !radio.classList.contains('selected')) { radio.click(); } } }); } else if(isFillBlank) { // 填空题 const input = question.querySelector('.fill_b .fillblank'); if(input) { input.value = answerText; // 触发input事件 const event = new Event('input', { bubbles: true }); input.dispatchEvent(event); } } }); log("自动答题完成!"); } // 添加自动答题按钮 function addAutoAnswerButton() { const btnArea = document.querySelector('.practice-action'); if(!btnArea) return; const btn = document.createElement('a'); btn.innerText = '自动答题'; btn.className = 'btn-public btn-min'; btn.href = 'javascript:void(0)'; btn.onclick = autoAnswerQuestions; btnArea.appendChild(btn); log("已添加自动答题按钮"); } // 初始化 function initAutoAnswer() { if(location.href.includes('/examSubmit/')) { log("检测到答题页面"); setTimeout(addAutoAnswerButton, 2000); } } initAutoAnswer(); // 脚本入口 initView(); //监听跳过视频按钮 $('#rl_passVideo').click(function(){passVideo();}); //监听url访问,当访问了加载题目的url时,将获取答案 $(document).ready(function(){ $(document).ajaxComplete(function (evt, request, settings) { if(settings.url.search('getExamPaper') != -1){ setting.logs.unshift("您已打开作业界面,5秒后将为您获取答案") setTimeout(initGetAnswer,5000, settings); } }); }) // 获取验证时间的函数 function getValidTime() { try { const data = localStorage.getItem('scriptValidUntil'); if (!data) return null; const { time, hash } = JSON.parse(data); if (!time || !hash) return null; // 验证哈希值 if (hash !== CryptoJS.SHA256(time.toString()).toString()) { localStorage.removeItem('scriptValidUntil'); return null; } return time; } catch (e) { console.error('获取验证时间出错:', e); localStorage.removeItem('scriptValidUntil'); return null; } }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址