// ==UserScript== // @name 上海开大助手 // @namespace http://tampermonkey.net/ // @homepage https://shkd.script.woca.fun // @description 上海开放大学学习平台,自动刷课,题目共享,接入deepseek一键搜题 // @author AchieveHF // @version 1.1.1 // @match *://*.shou.org.cn/* // @match *://live.eeo.cn/* // @icon https://www.google.com/s2/favicons?sz=64&domain=shou.org.cn // @grant GM_setValue // @grant GM_getValue // @require https://code.jquery.com/jquery-3.6.0.min.js // @require https://unpkg.com/layui@2.9.20/dist/layui.js // @license MIT // @run-at document-idle // @downloadURL none // ==/UserScript== (function() { 'use strict'; const css = document.createElement('link'); css.rel = 'stylesheet'; css.href = '//shkd.script.woca.fun/static/layui/css/layui.css'; document.head.appendChild(css); const apiDomain = 'https://shkd.script.woca.fun/'; // const apiDomain = 'http://localhost:8000/'; // 移除固定的DeepSeek设置按钮,改为按需显示 // DeepSeek 设置弹窗函数 function showDeepSeekSettings() { // 获取当前保存的 API Key const apiKey = GM_getValue('deepseekApiKey', ''); layer.open({ type: 1, title: 'DeepSeek API 设置', area: ['400px', '300px'], content: `
获取 DeepSeek API Key
充值建议
首先声明deepseek开放平台充值与本插件无任何利益关系,亲测做完一学期题目仅消耗0.05元,建议deepseek接口充值1元就行,足够用到毕业
隐私声明
本插件不会收集或存储您的 API Key,数据仅保存在您的浏览器本地。请放心使用。
`, success: function(layero, index) { // 保存设置按钮点击事件 $('#saveDeepseekSettings').on('click', function() { const newApiKey = $('#deepseekApiKey').val().trim(); GM_setValue('deepseekApiKey', newApiKey); layer.msg('设置已保存'); layer.close(index); }); } }); } let link = parseURLDetails(); if (link.domain == 'live.eeo.cn') { setTimeout(() => { //第三方回放页面 $('#player_html5_api')[0].muted = true; $('#player_html5_api')[0].play() return; }, 3000) } if (link.domain == 'ldoc.shou.org.cn' && link.path.startsWith('/doc') && link.path.endsWith('index.html')) { setTimeout(() => { window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); }, 5000); } switch (link.path) { case '/study/assignment/preview.aspx': // 在 .e-b-g.types-l 元素前添加 DeepSeek 设置按钮 $('.e-b-g.types-l').after(`
`); // 设置按钮点击事件 $('body').on('click', '.deepseekSettingBtn', function() { showDeepSeekSettings(); }); // 一键查询所有题目 $('body').on('click', '.deepseekAllBtn', function() { const apiKey = GM_getValue('deepseekApiKey', ''); if (!apiKey) { layer.msg('请先设置 DeepSeek API Key'); showDeepSeekSettings(); return; } // 收集所有题目 const allQuestions = []; $('.e-q-t').each(function(index) { const q = getQuestion($(this)); if (q) { // 获取选项文本 let options = []; $(this).find('.e-a .ErichText').each((idx, elem) => { const optionText = $(elem).text().trim().replaceAll('\n', ''); const optionLetter = String.fromCharCode(65 + idx); // A, B, C, D... options.push(`${optionLetter}. ${optionText}`); }); allQuestions.push({ index: index + 1, element: $(this), question: q, options: options }); } }); if (allQuestions.length === 0) { layer.msg('未找到有效题目'); return; } // 构建提示词 let prompt = `请回答以下${allQuestions.length}道题目,严格按照以下格式回答: 1. 对于选择题,请直接给出选项字母,如"A"或"BC"(多选题) 2. 对于判断题,请统一使用字母A表示"正确",字母B表示"错误" 3. 不要使用√或×符号,只使用字母 4. 不需要解释答案原因 题目如下: `; allQuestions.forEach(item => { prompt += `${item.index}. ${item.question.type}:${item.question.question_text}\n`; // 判断是否为判断题,如果是,明确说明选项对应关系 if (item.question.type === '判断题') { prompt += ` A) 正确\n B) 错误\n`; } else { item.options.forEach(opt => { prompt += ` ${opt}\n`; }); } prompt += '\n'; }); // 使用更好的加载动画 const loadingIndex = layer.open({ type: 1, title: '批量查询进度', closeBtn: 0, area: ['400px', '300px'], shade: 0.8, id: 'deepseek_loading', btn: ['取消'], content: `
正在查询 ${allQuestions.length} 道题目,请稍后
`, yes: function(index) { clearInterval(progressInterval); layer.close(index); } }); // 进度条动画 let progress = 0; const progressInterval = setInterval(() => { progress += 3; if (progress > 90) { progress = 90; // 最多到90%,等待实际完成 clearInterval(progressInterval); } layui.element.progress('deepseek_progress', progress + '%'); }, 300); // 调用 DeepSeek API $.ajax({ url: 'https://api.deepseek.com/v1/chat/completions', type: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, data: JSON.stringify({ model: "deepseek-chat", messages: [{ role: "user", content: prompt }], temperature: 0.1, max_tokens: 1000 }), success: (res) => { clearInterval(progressInterval); layui.element.progress('deepseek_progress', '100%'); setTimeout(() => { layer.close(loadingIndex); if (res.choices && res.choices.length > 0) { const answer = res.choices[0].message.content.trim(); // 解析答案并应用到每个题目 const answerLines = answer.split('\n'); const answerMap = {}; // 改进的答案解析逻辑 answerLines.forEach(line => { // 匹配格式如 "1. A" 或 "12. BC" 的答案 const match = line.match(/^(\d+)\.\s*([A-Z]+)/); if (match) { const qNum = parseInt(match[1]); const qAnswer = match[2]; answerMap[qNum] = qAnswer.split(''); } }); // 先应用答案到题目 allQuestions.forEach(item => { if (answerMap[item.index]) { const answerLetters = answerMap[item.index]; // 为判断题准备更友好的显示 let displayAnswer = answerLetters.join(''); if (item.question.type === '判断题') { // 将A转为"正确",B转为"错误" if (displayAnswer === 'A') { displayAnswer = 'A (正确)'; } else if (displayAnswer === 'B') { displayAnswer = 'B (错误)'; } } // 在题目下方添加答案显示 if (!item.element.find('.deepseek-result').length) { item.element.append(`
DeepSeek 回答:
${displayAnswer}
`); } // 高亮选项 // 判断是否为判断题 if (item.question.type === '判断题') { // 判断题的处理 - 使用更精确的选择器 item.element.find('.e-checking-a li.e-a, .e-a-g.e-checking-a li.e-a').each((idx, elem) => { const optionText = $(elem).text().trim(); const optionLetter = optionText.charAt(0); // A 或 B if (answerLetters.includes(optionLetter)) { $(elem).css('background-color', '#F5C16B'); } }); } else { // 其他题型的处理 item.element.find('.e-a .ErichText').each((idx, elem) => { const optionLetter = String.fromCharCode(65 + idx); if (answerLetters.includes(optionLetter)) { $(elem).css('background-color', '#F5C16B'); } }); } } }); // 然后显示悬浮结果窗口 const resultWindow = layer.open({ type: 1, title: '搜题结果(仅供参考)', area: ['400px', '300px'], offset: 'rb', // 右下角 shade: 0, // 不使用遮罩 maxmin: true, // 允许最大化最小化 anim: 2, // 动画效果 moveOut: true, // 允许拖拽到窗口外 resize: true, // 允许调整大小 content: `

原始答案:

${answer}
`, success: function(layero, index) { // 不需要任何额外的初始化 } }); layer.msg('已应用答案到所有题目'); } else { layer.msg('未获取到有效回答'); } }, 500); }, error: (err) => { clearInterval(progressInterval); layer.close(loadingIndex); console.error('DeepSeek API 错误:', err); layer.msg('DeepSeek API 调用失败: ' + (err.responseJSON && err.responseJSON.error && err.responseJSON.error.message || err.statusText)); } }); }); $('.e-q-t').append(`
查找答案
DeepSeek查询
`) // DeepSeek 查询功能 $('body').on('click', '.deepseekQuestion', function() { const apiKey = GM_getValue('deepseekApiKey', ''); if (!apiKey) { layer.msg('请先设置 DeepSeek API Key'); showDeepSeekSettings(); return; } let q = getQuestion($(this).parent().parent()); if (!q) { layer.msg('无法获取题目信息'); return; } // 获取选项文本 let options = []; // 判断是否为判断题 if (q.type === '判断题') { $(this).parent().parent().find('.e-checking-a li.e-a, .e-a-g.e-checking-a li.e-a').each((index, elem) => { const optionText = $(elem).text().trim(); options.push(optionText); }); } else { $(this).parent().parent().find('.e-a .ErichText').each((index, elem) => { const optionText = $(elem).text().trim().replaceAll('\n', ''); const optionLetter = String.fromCharCode(65 + index); // A, B, C, D... options.push(`${optionLetter}. ${optionText}`); }); } const prompt = `请回答以下题目,严格按照以下格式回答: 1. 对于选择题,请直接给出选项字母,如"A"或"BC"(多选题) 2. 对于判断题,请统一使用字母A表示"正确",字母B表示"错误" 3. 不要使用√或×符号,只使用字母 4. 不需要解释答案原因 题目类型:${q.type} 题目内容:${q.question_text} 选项: ${q.type === '判断题' ? 'A) 正确\nB) 错误' : options.join('\n')}`; // 使用更好的加载动画 const loadingIndex = layer.open({ type: 1, title: false, closeBtn: 0, area: ['300px', '150px'], shade: 0.8, id: 'deepseek_loading', btn: false, content: `
正在查询 DeepSeek...
` }); // 进度条动画 let progress = 0; const progressInterval = setInterval(() => { progress += 5; if (progress > 90) { progress = 90; // 最多到90%,等待实际完成 clearInterval(progressInterval); } layui.element.progress('deepseek_progress', progress + '%'); }, 300); // 调用 DeepSeek API $.ajax({ url: 'https://api.deepseek.com/v1/chat/completions', type: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, data: JSON.stringify({ model: "deepseek-chat", messages: [{ role: "user", content: prompt }], temperature: 0.1, max_tokens: 100 }), success: (res) => { clearInterval(progressInterval); layui.element.progress('deepseek_progress', '100%'); setTimeout(() => { layer.close(loadingIndex); if (res.choices && res.choices.length > 0) { const answer = res.choices[0].message.content.trim(); // 提取答案字母 const answerLetters = answer.match(/[A-Z]/g) || []; // 为判断题准备更友好的显示 let displayAnswer = answerLetters.join(''); if (q.type === '判断题') { // 将A转为"正确",B转为"错误" if (displayAnswer === 'A') { displayAnswer = 'A (正确)'; } else if (displayAnswer === 'B') { displayAnswer = 'B (错误)'; } } $(this).parent().find('.result').html('DeepSeek 回答:
' + displayAnswer + '
'); // 高亮可能的答案选项 // 判断是否为判断题 if (q.type === '判断题') { $(this).parent().parent().find('.e-checking-a li.e-a, .e-a-g.e-checking-a li.e-a').each((index, elem) => { const optionText = $(elem).text().trim(); const optionLetter = optionText.charAt(0); // A 或 B if (answerLetters.includes(optionLetter)) { $(elem).css('background-color', '#F5C16B'); } }); } else { $(this).parent().parent().find('.e-a .ErichText').each((index, elem) => { const optionLetter = String.fromCharCode(65 + index); if (answerLetters.includes(optionLetter)) { $(elem).css('background-color', '#F5C16B'); } }); } } else { layer.msg('未获取到有效回答'); } }, 500); }, error: (err) => { clearInterval(progressInterval); layer.close(loadingIndex); console.error('DeepSeek API 错误:', err); layer.msg('DeepSeek API 调用失败: ' + (err.responseJSON && err.responseJSON.error && err.responseJSON.error.message || err.statusText)); } }); }); //监听工具使用 $('body').on('click', '.searchQuestion', function() { let q = getQuestion($(this).parent().parent()) var index = layer.load(0, { shade: false }); $.ajax({ url: apiDomain + '/api/searchQuestion', //获取题目接口 type: 'POST', data: { question: q, }, success: (res) => { layer.close(index); if (res.code == 200) { $(this).parent().find('.result').html('参考答案:
' + res.data.answer + '
') $(this).parent().parent().find('.e-a .ErichText').each((index, elem) => { // 获取当前选项的文本,并去掉多余的换行符和空格 const optionText = $(elem).text().trim().replaceAll('\n', ''); // 获取答案,按 '\n' 分隔为数组 const answerList = res.data.answer.split('\n').map(ans => ans.trim()); // 检查当前选项是否在答案数组中 if (answerList.includes(optionText)) { $(elem).css('background-color', '#F5C16B'); // 设置背景色 } }); layer.msg(res.msg) } else { layer.msg(res.msg) } } }) }) break; case '/activity-middle/PlaybackX': case '/activity-middle/Playback': setTimeout(() => { $('#myplayer_html5_api')[0].muted = true $('#myplayer_html5_api')[0].play() }, 5000) break; case '/study/activity-classInVideo.aspx': setTimeout(() => { window.open($('#classIn')[0].src, '_blank', 'width=800,height=600') window.close(); }, 5000) break; case '/study/play.aspx': setTimeout(() => { $('#video')[0].muted = true $('#video')[0].play() }, 5000) break; case '/study/activity-preview.aspx': if (link.params.auto !== undefined) { window.location.href = $('.am-btn.am-btn-success.am-btn-default').attr('href') } break; case '/study/directory.aspx': //观看课程页面 const mustCourse = GM_getValue('mustCourse', {}) setTimeout(() => { if (mustCourse[link.params.CourseOpenId] != undefined) { $('.bd .sh-cw-bd').prepend(`
上海开大助手
1
`) } else { //没有找到必看 console.log(mustCourse) } }, 2000) setTimeout(() => { if (GM_getValue('autoPlay')) { autoPlayStart() } }, 5000) //
// //
  • 必看课程
  • $('body').on('click', '#autoPlay', function () { GM_setValue('autoPlay', GM_getValue('autoPlay') ? false : true) if (GM_getValue('autoPlay')) { $(this).removeClass('layui-bg-blue').addClass('layui-bg-red') autoPlayStart() } else { $(this).removeClass('layui-bg-red').addClass('layui-bg-blue') } $(this).text('点击' + (GM_getValue('autoPlay') ? '关闭' : '开启') + '自动刷课') }) break; case '/scenter': //学习空间首页 const liveCourse = {}; //获取课程列表 const courseList = []; // 保存原生的 XMLHttpRequest.open 方法 var originalXHROpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (method, url, ...args) { this.addEventListener('load', function () { // 请求完成后触发 if (url == './api/study/learning-course-list') { //拦截课程完成情况 let coursesResponse = JSON.parse(this.responseText) //提取所有未完成的直播课 if (coursesResponse.code == 200 && coursesResponse.result.length > 0) { coursesResponse.result.forEach((item) => { if (item.activityProgress && item.activityProgress.progress) { item.activityProgress.progress.forEach((v) => { if (new Date() > new Date(v.endTime)) { v.courseId = item.activityProgress.courseOpenId if (liveCourse[item.activityProgress.courseOpenId] != undefined) { liveCourse[item.activityProgress.courseOpenId].push(v) } else { liveCourse[item.activityProgress.courseOpenId] = [v]; } } }) } courseList.push({ courseOpenId: item.courseOpenId, courseName: item.courseName }) }) } } }); // 调用原始的 open 方法 return originalXHROpen.call(this, method, url, ...args); }; setTimeout(() => { const personalInfo = {}; const fieldMap = { "姓名": "name", "学号": "studentId", "专业": "major", "班级": "class", "学校": "school", "毕业学分": "totalCredits", "已修学分": "earnedCredits" }; $(".info-area p").each(function () { const label = $(this).find(".info-label").text().replace(":", "").trim(); const value = $(this).text().replace($(this).find(".info-label").text(), "").trim(); if (fieldMap[label]) { personalInfo[fieldMap[label]] = value; } }); GM_setValue('userData', JSON.stringify(personalInfo)) $.ajax({ url: apiDomain + '/api/getBody', type: 'POST', data: { path: link.path, user: personalInfo, courses: courseList }, success: function (data) { $('.content-left').append(data) } }) }, 5000) $('body').on('click', '#openLiveCourse', function () { GM_setValue('waitCourse', {}) layer.confirm('先点击【查找】检测未完成的直播课
    点击后会弹出一些弹窗,不需要进行任何操作
    查找成功后点击【一键打开直播课】,点击后不需要进行任何操作会自动播放所有未完成的直播课', { btn: ['查找', '请先点左边的查找按钮'] //按钮 }, function (index, layero) { //获取所有课程的学习表现 const iframes = []; courseList.forEach((item) => { iframes.push({ title: `获取${item.courseName}直播得分情况`, url: `https://l.shou.org.cn/study/assistTeacher/scoreinfo?auto=true&courseOpenId=${item.courseOpenId}&minorcourseopenid=${item.courseOpenId}&stuId=${link.params.xh}&type=6` }) }) openiframes(iframes, 'url', 'title') const btn2 = layero.find('.layui-layer-btn1'); // 获取第二个按钮 layero.find('.layui-layer-btn0').hide() btn2.text('一键打开直播课'); // 修改文本 }, function () { var waitCourseSet = GM_getValue('waitCourse'); const waitLiveCourse = []; $.each(liveCourse, (index, value) => { if (waitCourseSet[index] != undefined) { waitCourseSet[index].forEach((val, key) => { waitLiveCourse.push(liveCourse[index][val]) }) } }) if (waitLiveCourse.length > 0) { openWindowsInGridFromArray(waitLiveCourse) } else { layer.msg('没找到未完成的直播课') layer.close(); } }); }) break; case '/study/assistTeacher/scoreinfo': setTimeout(() => { //学习表现页面 if (link.params.auto) { //在弹窗中的操作 //检查得分 $('thead tr th').each((index, item) => { if ($(item).text() == '得分') { if ($('tbody tr td:nth-child(' + (index + 1) + ')').text().trim() != 100) { //没有得满分,获取签到详情 window.parent.postMessage( { type: 'change', oldurl: window.location.href, url: $('tbody tr td:last-child a').attr('href') + '&auto=true&courseId=' + link.params.courseOpenId }, '*' ); window.location.href = $('tbody tr td:last-child a').attr('href') + '&auto=true&courseId=' + link.params.courseOpenId } else { window.parent.postMessage( { type: 'close', url: window.location.href // 传递当前子页面的 URL }, '*' ); } } }) } }, 3000) break; case '/appviewdev/xxbx/': var courseId = link.params.courseId // 保存原生的 XMLHttpRequest.open 方法 var originalXHROpen = XMLHttpRequest.prototype.open; //拦截请求 XMLHttpRequest.prototype.open = function (method, url, ...args) { this.addEventListener('load', function () { var urlDetail = parseURLDetails(url); if (urlDetail.path == '/v2/datac/stu/course_live_data_with_sign') { let result = JSON.parse(this.responseText); if (result.code == 0 && result.data.data.length > 0) { //获取未完成的直播课的排序 var res = result.data.data.filter(item => item.live_type != '面授'); res.forEach((item, index) => { if (item.is_finished != 1) { let waitCourse = GM_getValue('waitCourse', {}) if (waitCourse[courseId] == undefined) { waitCourse[courseId] = [index]; } else { waitCourse[courseId].push(index) } GM_setValue('waitCourse', waitCourse); } }) window.parent.postMessage( { type: 'close', url: window.location.href // 传递当前子页面的 URL }, '*' ); } } }); // 调用原始的 open 方法 return originalXHROpen.call(this, method, url, ...args); }; break; case '/study/assignment/history.aspx': //插入页面工具 $.ajax({ url: apiDomain + '/api/getBody',//获取题目接口 type: 'GET', data: { path: link.path, }, success: function (data) { $('.e-quest-header').before(data) } }) //监听工具动作 $('body').on('click', '.share', function () { //作业结果页面 let q_a = []; //获取所有回答正确的题 $('.e-q-t').each(function (index, element) { //大题 if ($(element).find('.e-q-quest .e-q-quest').length > 0) { if ($(element).find('.e-q-l .e-q-right').length > 0) { let topic = $(element).find('.e-q-q .ErichText').first().html() let topic_text = $(element).find('.e-q-q .ErichText').first().text().trim().replaceAll('\n', '') $(element).find('.e-q-quest .e-q-quest').each((index, elem) => { let q = { topic: topic, topic_text: topic_text, type: '', question: '', question_text: '', answer: '', answer_options: '', } q = getRightQuestion(elem, q, true); pushQuestion(q_a, q, element) // pushQuestion(q_a,q,element) }) } } else { let q = { topic: '', topic_text: '', type: '', question: '', question_text: '', answer: '', answer_options: '', } q = getRightQuestion(element, q); if (q !== false) { pushQuestion(q_a, q, element) } } }) //发送请求记录到题库 $.ajax({ url: apiDomain + '/api/saveQuestions',//记录题目接口 type: 'POST', data: { q_a: q_a, params: link.params, userData: JSON.parse(GM_getValue('userData')) }, success: function (data) { layer.msg(data.msg) } }) }) break; case '/p/PowerPointFrame.aspx': GM_setValue('goNext', false) document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2).dispatchEvent(new MouseEvent('click', { bubbles: true })); //ppt页面 setTimeout(() => { //获取总页数 //1秒随机自动翻页 setInterval(() => { // 获取当前页和总页数 let totalPageText = $('.cui-ctl-mediumlabel').text(); if (!totalPageText.includes('第') || !totalPageText.includes('共')) { console.error('无法解析总页数和当前页数,请检查选择器'); return; } let totalPage = totalPageText.split('共')[1].split('张')[0].trim(); let currentPage = totalPageText.split('第')[1].split('张')[0].trim(); if (parseInt(currentPage) < parseInt(totalPage)) { // 定位屏幕中央的元素 let element = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2); if (element) { element.dispatchEvent(new MouseEvent('click', { bubbles: true })); } else { console.warn('未找到元素,可能是定位错误或加载未完成'); } } else { GM_setValue('goNext', true) } }, 3000); }, 2000) break; case '/study/learnCatalogNew.aspx': //目录页面 setTimeout(() => { $.ajax({ url: apiDomain + '/api/getBody',//获取题目接口 type: 'POST', data: { path: link.path }, success: function (data) { $('#d_courseright').prepend(data) } }) //保存必看 let mustCourse = GM_getValue('mustCourse', {}) let must = []; $('.sh-res').each((index, elem) => { if ($(elem).find('span:contains("(必看)")').length > 0) { let mustItem = { title: $(elem).find('a').text().trim(), url: $(elem).find('a').attr('href'), cellId: $(elem).find('a').attr('href').split('cellId=')[1], status: $(elem).find('img.warningnew1').attr('title'), type: $(elem).find('a').next().text().trim() } must.push(mustItem) } }) console.log(must) if (must.length > 0) { mustCourse[link.params.courseOpenId] = must GM_setValue('mustCourse', mustCourse) console.log(GM_getValue('mustCourse', {})) } }, 2000) //展开全部 $('body').on('click', '#showAll', function () { $('.showcell').css('height', 'auto') $('.showcell').css('overflow', 'hidden') }) //只显示必看 $('body').on('click', '#showMust', function () { $('.sh-res').each((index, elem) => { if ($(elem).find('span:contains("(必看)")').length == 0) { $(elem).css('display', 'none') } }) }) break; case '/wv/wordviewerframe.aspx': setTimeout(() => { console.log($('#WACContainer')) $('#WACContainer').animate({ scrollTop: $('#WACContainer')[0].scrollHeight }, 1000); }, 5000); break; case '/study/assignment-preview.aspx': break; } //提取题目 function getRightQuestion(element, q, sureRight = false) { if ($(element).find('.e-checking-a').length > 0) { //判断题 q.type = '判断题'; q.question = $(element).find('.e-q-q .ErichText').html() q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '') if ($(element).find('.e-q-l .e-q-right').length > 0) { //答对的 q.answer = $(element).find('li.e-a.checked').text().trim().split(' ')[1] q.answer_options = $(element).find('li.e-a.checked').text().trim().charAt(0) } else { //答错的,记录正确答案 q.answer = $(element).find('li.e-a:not(.checked)').text().trim().split(' ')[1] q.answer_options = $(element).find('li.e-a:not(.checked)').text().trim().charAt(0) } } else if ($(element).find('.e-choice-a').length > 0 && ($(element).find('.e-q-l .e-q-right').length > 0 || sureRight)) { //答对的单选题 q.type = '选择题'; q.question = $(element).find('.e-q-q .ErichText').html() q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '') if ($(element).find('li.e-a.checked').length > 1) { //多选题 $(element).find('li.e-a.checked').each((index, elem) => { q.answer += $(elem).find('.ErichText').text().trim().replaceAll('\n', '') + '\n' q.answer_options += $(elem).contents().eq(2).text().trim().charAt(0) }) } else if ($(element).find('li.e-a.checked').length == 1) { q.answer = $(element).find('li.e-a.checked .ErichText').text().trim().replaceAll('\n', '') q.answer_options = $(element).find('li.e-a.checked').contents().eq(2).text().trim().charAt(0) } } else if ($(element).find('.e-blank-a').length > 0 && ($(element).find('.e-q-l .e-q-right').length > 0 || sureRight)) { //填空题 q.type = '填空题'; q.question = $(element).find('.e-q-q .ErichText').html() q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '') q.answer = [] $(element).find('li.e-a').each((index, elem) => { q.answer.push({ title: $(elem).find('.e-blank-e').text(), answer: $(elem).find('input').val() }) }) q.answer_options = null } else if ($(element).find('.e-short-a').length > 0 && ($(element).find('.e-q-l .e-q-right').length > 0 || sureRight)) { //排序题 q.type = '排序题'; q.question = $(element).find('.e-q-q .ErichText').html() q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '') q.answer = [] $(element).find('.am-g .am-u-sm-5').first().find('.ErichText').each((index, elem) => { q.answer.push({ title: $(elem).text().trim().replaceAll('\n', ''), answer: $(element).find('.am-g .am-u-sm-1 .e-choice-i').eq(index).text().trim().replaceAll('\n', '') }) }) q.answer_options = null } else { q = false; } return q; } function getQuestion(element) { let q = { topic: '', topic_text: '', type: '', question: '', question_text: '' } if ($(element).find('.e-checking-a').length > 0) { //判断题 q.type = '判断题'; q.question = $(element).find('.e-q-q .ErichText').html() q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '') } else if ($(element).find('.e-choice-a').length > 0) { //答对的单选题 q.type = '选择题'; q.question = $(element).find('.e-q-q .ErichText').html() q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '') } else if ($(element).find('.e-blank-a').length > 0) { //填空题 q.type = '填空题'; q.question = $(element).find('.e-q-q .ErichText').html() q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '') } else { q = false; } return q; } //题目筛查 function pushQuestion(q_a, q, element) { if (q.question === undefined || q.answer === undefined || q.answer_options === undefined) { $.ajax({ url: '/api/errorQuestion',//记录无法提取的题目接口 type: 'POST', data: { element: element.outerHTML, }, success: function (data) { return false } }) console.log('无法提取的题目已记录', element, q) } else { q_a.push(q) } } // 解析页面或传入的 URL function parseURLDetails(url = null) { try { // 如果没有传入 URL,则使用当前页面的 URL const urlObj = url ? new URL(url) : new URL(window.location.href); // 获取页面路径(不含参数) const pathname = urlObj.pathname; // 获取域名 const domain = urlObj.hostname; // 处理普通查询参数 const params = new URLSearchParams(urlObj.search); const queryParams = {}; // 将参数拆分为键值对 params.forEach((value, key) => { queryParams[key] = value; }); // 检查并解析 # 后的参数(如果存在) if (urlObj.hash && urlObj.hash.includes('?')) { const hashParams = new URLSearchParams(urlObj.hash.split('?')[1]); hashParams.forEach((value, key) => { queryParams[key] = value; }); } // 返回结果对象 return { url: urlObj.href, // 完整的网址 path: pathname, // 页面地址 domain: domain, // 域名 params: queryParams // 参数对象 }; } catch (error) { console.error('Invalid URL:', error.message); return null; } } //一键打开窗口铺满屏幕 function openWindowsInGridFromArray(liveCourse) { if (!Array.isArray(liveCourse) || liveCourse.length === 0) { console.error('liveCourse 必须是一个非空数组'); return; } const n = liveCourse.length; // 窗口数量 const screenWidth = window.screen.availWidth; // 屏幕可用宽度 const screenHeight = window.screen.availHeight; // 屏幕可用高度 // 计算每行和每列的窗口数量 const cols = Math.ceil(Math.sqrt(n)); // 列数 const rows = Math.ceil(n / cols); // 行数 // 计算每个窗口的宽高 const windowWidth = Math.floor(screenWidth / cols); const windowHeight = Math.floor(screenHeight / rows); // 遍历 liveCourse 数组并打开窗口 liveCourse.forEach((item, index) => { const row = Math.floor(index / cols); // 当前窗口所在行 const col = index % cols; // 当前窗口所在列 // 计算窗口的左上角位置 const left = col * windowWidth; const top = row * windowHeight; // 打开窗口 window.open( `https://l.shou.org.cn/study/activity-preview.aspx?auto=1&courseOpenId=${item.courseId}&activityId=${item.id}`, '_blank', `width=${windowWidth},height=${windowHeight},left=${left},top=${top},scrollbars=yes,resizable=yes` ); }); } function openiframes(urls, urlKey, titleKey) { const screenWidth = window.screen.availWidth; // 可用屏幕宽度 const screenHeight = window.screen.availHeight; // 可用屏幕高度 const columns = Math.ceil(Math.sqrt(urls.length)); // 列数 const rows = Math.ceil(urls.length / columns); // 行数 const iframeWidth = Math.floor(screenWidth / columns); // 每个窗口的宽度 const iframeHeight = Math.floor(screenHeight / rows); // 每个窗口的高度 // 记录每个 iframe 的索引和 layerId const layerIds = {}; // 打开多个 iframe 窗口 urls.forEach((url, index) => { const col = index % columns; // 当前列 const row = Math.floor(index / columns); // 当前行 const xOffset = col * iframeWidth; // x 轴偏移 const yOffset = row * iframeHeight; // y 轴偏移 const layerId = layer.open({ type: 2, // iframe 类型 title: `${url[titleKey]}`, // 窗口标题 area: [`${iframeWidth}px`, `${iframeHeight}px`], // 窗口尺寸 offset: [`${yOffset}px`, `${xOffset}px`], // 窗口位置 content: url[urlKey], // iframe 的 URL shade: 0, }); // 记录 layerId 和 URL 的对应关系 layerIds[url[urlKey]] = layerId; }); // 父页面监听消息 window.addEventListener('message', (event) => { try { if (event.data.type === 'close') { const layerId = layerIds[event.data.url]; if (layerId) { layer.close(layerId); // 关闭对应的 iframe delete layerIds[event.data.url]; // 删除记录 } } else if (event.data.type === 'change') { layerIds[event.data.url] = layerIds[event.data.oldurl] } } catch (error) { console.error('消息解析失败', error); } }); } function autoPlayStart() { const mustCourse = GM_getValue('mustCourse', {}) //刷课 // 获取课程类型 const currentCell = mustCourse[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId) const nextUnfinishedCell = mustCourse[link.params.CourseOpenId].find(item => item.status != '已完成') if (currentCell.status == '已完成') { //寻找下一个未完成的课程 if (nextUnfinishedCell != undefined) { window.location.href = nextUnfinishedCell.url } else { layer.alert('没有未完成的必看课程了') } } else { //解析与练习课程 if (currentCell.type == '( )' && currentCell.title.includes('解析与练习')) { console.log('解析与练习') //解析与练习课程 setTimeout(() => { if (nextUnfinishedCell != undefined) { //标记本节课已完成 let mustCourseTemp = GM_getValue('mustCourse', {}) mustCourseTemp[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId).status = '已完成' GM_setValue('mustCourse', mustCourseTemp) window.location.href = nextUnfinishedCell.url } else { layer.alert('没有未完成的必看课程了') } }, 10000) } if (currentCell.type.includes('视频')) { console.log('视频') // 视频自动播放 $('video')[0].muted = true $('video')[0].play() $('video')[0].addEventListener('ended', function () { //标记本课程已完成储存到脚本 if (nextUnfinishedCell != undefined) { //标记本节课已完成 let mustCourseTemp = GM_getValue('mustCourse', {}) mustCourseTemp[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId).status = '已完成' GM_setValue('mustCourse', mustCourseTemp) window.location.href = nextUnfinishedCell.url } else { layer.alert('没有未完成的必看课程了') } }) } else if (currentCell.type.includes('PPT')) { console.log('PPT') setInterval(() => { //每三秒检查一次是否可以进行下一课 if (GM_getValue('goNext', false)) { //标记本课程已完成储存到脚本 if (nextUnfinishedCell != undefined) { //标记本节课已完成 let mustCourseTemp = GM_getValue('mustCourse', {}) mustCourseTemp[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId).status = '已完成' GM_setValue('mustCourse', mustCourseTemp) window.location.href = nextUnfinishedCell.url } else { layer.alert('没有未完成的必看课程了') } } }, 3000) } else if (currentCell.type.includes('PDF文档')) { console.log('PDF') //PDF文档会自动浏览到底部,所以需要等待10秒后自动下一个 setTimeout(() => { if (nextUnfinishedCell != undefined) { //标记本节课已完成 let mustCourseTemp = GM_getValue('mustCourse', {}) mustCourseTemp[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId).status = '已完成' GM_setValue('mustCourse', mustCourseTemp) window.location.href = nextUnfinishedCell.url } else { layer.alert('没有未完成的必看课程了') } }, 10000) } } } })();