// ==UserScript==
// @name 学习通作业复习助手
// @namespace http://xuanyue1024.net/
// @version 0.8
// @description 为作业添加答题按钮
// @author 竹林听雨
// @match file:///*.html
// @match https://mooc1.chaoxing.com/mooc-ans/mooc2/work/view*
// @match *://*/*.html
// @license MIT
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 等待页面加载完成
function waitForElement(selector, callback) {
if (document.querySelector(selector)) {
callback();
} else {
setTimeout(() => waitForElement(selector, callback), 500);
}
}
// 主函数
function addAnswerButtons() {
// 添加清除记录按钮
addClearButton();
// 查找所有题目
const questions = document.querySelectorAll('.questionLi');
questions.forEach(question => {
// 检查是否已经添加过按钮
if (question.querySelector('.custom-answer-buttons')) {
return;
}
// 获取题号并移除对应题号的active类
const questionId = question.getAttribute('id');
if (questionId) {
// 恢复上次的作答记录
restoreAnswer(question, questionId);
}
// 隐藏答案区域
const answerArea = question.querySelector('.mark_answer');
if (answerArea) {
answerArea.style.setProperty('display', 'none', 'important');
}
// 创建按钮容器
const buttonContainer = document.createElement('div');
buttonContainer.className = 'custom-answer-buttons';
buttonContainer.style.cssText = 'margin: 10px 0; padding: 10px; background: #f5f5f5; border-radius: 5px;';
// 添加展示答案按钮
const showAnswerButton = document.createElement('button');
showAnswerButton.textContent = '显示答案';
showAnswerButton.style.cssText = 'margin: 0 5px; padding: 5px 15px; border: 1px solid #ddd; border-radius: 3px; cursor: pointer; background-color: #4CAF50; color: white;';
showAnswerButton.addEventListener('click', () => toggleAnswer(question));
// 添加标记按钮
const markButton = document.createElement('button');
markButton.textContent = '标记题目';
markButton.style.cssText = 'margin: 0 5px; padding: 5px 15px; border: 1px solid #ddd; border-radius: 3px; cursor: pointer; background-color: #fff; color: #666;';
markButton.addEventListener('click', () => toggleMarkQuestion(question, markButton));
// 先添加显示答案按钮,再添加标记按钮
buttonContainer.appendChild(showAnswerButton);
buttonContainer.appendChild(markButton);
// 获取题目类型
const titleElement = question.querySelector('.colorShallow');
if (titleElement) {
const questionType = titleElement.textContent;
// 为选项添加点击事件
if (questionType.includes('单选题')) {
addSingleChoiceHandlers(question);
} else if (questionType.includes('判断题')) {
addTrueFalseHandlers(question);
}
}
// 在题目内容后插入按钮容器
const content = question.querySelector('.aiAreaContent');
if (content) {
content.appendChild(buttonContainer);
}
// 恢复标记状态
if (questionId) {
const marks = JSON.parse(localStorage.getItem('questionMarks') || '{}');
if (marks[questionId]) {
markButton.textContent = '取消标记';
markButton.style.backgroundColor = '#FFA500';
markButton.style.color = '#fff';
question.style.backgroundColor = '#FFF3E0';
// 恢复题号标记图标
const questionNumber = questionId.replace('question', '');
const answerSheetItem = document.querySelector(`#answerSheet${questionNumber}`);
if (answerSheetItem && !answerSheetItem.querySelector('.mark-icon')) {
const markIcon = document.createElement('span');
markIcon.className = 'mark-icon';
markIcon.innerHTML = '★';
markIcon.style.color = '#FF4444';
answerSheetItem.appendChild(markIcon);
}
}
}
});
}
// 为单选题添加点击处理
function addSingleChoiceHandlers(question) {
const options = question.querySelectorAll('.mark_letter li');
options.forEach((option, index) => {
option.style.cursor = 'pointer';
option.addEventListener('click', () => selectAnswer(question, index, 'single'));
});
}
// 为判断题添加点击处理
function addTrueFalseHandlers(question) {
const options = question.querySelectorAll('.mark_letter li');
options.forEach((option, index) => {
option.style.cursor = 'pointer';
option.addEventListener('click', () => selectAnswer(question, index, 'judge'));
});
}
// 切换显示/隐藏答案
function toggleAnswer(question) {
const answerContainer = question.querySelector('.mark_answer');
if (!answerContainer) return;
const isHidden = answerContainer.style.display === 'none' || getComputedStyle(answerContainer).display === 'none';
answerContainer.style.setProperty('display', isHidden ? 'block' : 'none', 'important');
// 更新按钮文本
const showAnswerButton = question.querySelector('.custom-answer-buttons button:first-child');
if (showAnswerButton) {
showAnswerButton.textContent = isHidden ? '隐藏答案' : '显示答案';
showAnswerButton.style.backgroundColor = isHidden ? '#f44336' : '#4CAF50';
}
}
// 选择答案
function selectAnswer(question, index, type) {
// 获取答案区域的父元素
const answerContainer = question.querySelector('.mark_answer');
if (!answerContainer) return;
// 获取所有选项
const options = question.querySelectorAll('.mark_letter li');
// 检查是否是重复点击同一个选项
const isSelected = options[index].style.backgroundColor === 'rgb(240, 240, 240)';
// 获取题目ID
const questionId = question.getAttribute('id');
const questionNumber = questionId.replace('question', '');
const answerSheetItem = document.querySelector(`#answerSheet${questionNumber}`);
// 如果是重复点击,则取消选择
if (isSelected) {
// 重置选项样式
options[index].style.backgroundColor = '';
options[index].style.color = '';
// 隐藏答案区域
answerContainer.style.setProperty('display', 'none', 'important');
// 移除题号的active类并重置颜色
if (answerSheetItem) {
answerSheetItem.classList.remove('active');
answerSheetItem.style.backgroundColor = '#fff';
answerSheetItem.style.color = '#6BA9FF';
}
// 从localStorage中移除该题的记录
if (questionId) {
let answers = JSON.parse(localStorage.getItem('answersRecord') || '{}');
delete answers[questionId];
localStorage.setItem('answersRecord', JSON.stringify(answers));
}
return;
}
// 如果不是重复点击,执行正常的选择逻辑
if (questionId) {
saveAnswer(questionId, index, type);
}
// 隐藏"我的答案"部分
const myAnswerSpan = answerContainer.querySelector('.colorDeep.marginRight40.fl');
const myAnswerText = answerContainer.querySelector('.element-invisible-hidden.colorDeep');
if (myAnswerSpan) {
myAnswerSpan.style.display = 'none';
}
if (myAnswerText) {
myAnswerText.style.display = 'none';
}
// 隐藏对错标记部分
const markScore = answerContainer.querySelector('.mark_score');
if (markScore) {
markScore.style.display = 'none';
}
// 显示答案区域
answerContainer.style.setProperty('display', 'block', 'important');
// 高亮选中的选项
options.forEach((option, i) => {
if (i === index) {
option.style.backgroundColor = '#f0f0f0';
option.style.color = '#6C07A2';
} else {
option.style.backgroundColor = '';
option.style.color = '';
}
});
// 更新题号状态
if (answerSheetItem) {
answerSheetItem.classList.add('active');
answerSheetItem.style.backgroundColor = '#BFDAFF';
answerSheetItem.style.color = '#6BA9FF';
}
}
// 添加清除记录按钮
function addClearButton() {
const container = document.querySelector('.fanyaMarking_left');
if (!container || container.querySelector('.clear-answers-button')) return;
// 创建按钮容器
const buttonContainer = document.createElement('div');
buttonContainer.className = 'clear-buttons-container';
buttonContainer.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 1000; display: flex; gap: 10px;';
// 清除作答记录按钮
const clearAnswersButton = document.createElement('button');
clearAnswersButton.className = 'clear-answers-button';
clearAnswersButton.textContent = '清除作答记录';
clearAnswersButton.style.cssText = 'padding: 8px 16px; background-color: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer;';
clearAnswersButton.addEventListener('click', clearAllAnswers);
// 清除标记按钮
const clearMarksButton = document.createElement('button');
clearMarksButton.className = 'clear-marks-button';
clearMarksButton.textContent = '清除所有标记';
clearMarksButton.style.cssText = 'padding: 8px 16px; background-color: #FFA500; color: white; border: none; border-radius: 4px; cursor: pointer;';
clearMarksButton.addEventListener('click', clearAllMarks);
// 添加按钮到容器
buttonContainer.appendChild(clearAnswersButton);
buttonContainer.appendChild(clearMarksButton);
container.appendChild(buttonContainer);
}
// 清除所有作答记录
function clearAllAnswers() {
if (confirm('确定要清除所有作答记录吗?')) {
localStorage.removeItem('answersRecord');
// 刷新页面
window.location.reload();
}
}
// 保存答案
function saveAnswer(questionId, index, type) {
let answers = JSON.parse(localStorage.getItem('answersRecord') || '{}');
answers[questionId] = { index, type };
localStorage.setItem('answersRecord', JSON.stringify(answers));
}
// 恢复答案
function restoreAnswer(question, questionId) {
const answers = JSON.parse(localStorage.getItem('answersRecord') || '{}');
const savedAnswer = answers[questionId];
if (savedAnswer) {
// 恢复选择
selectAnswer(question, savedAnswer.index, savedAnswer.type);
// 恢复题号状态
const questionNumber = questionId.replace('question', '');
const answerSheetItem = document.querySelector(`#answerSheet${questionNumber}`);
if (answerSheetItem) {
answerSheetItem.classList.add('active');
// 确保颜色正确
answerSheetItem.style.backgroundColor = '#BFDAFF';
answerSheetItem.style.color = '#6BA9FF';
}
} else {
// 如果没有保存的答案,移除题号的active类并重置颜色
const questionNumber = questionId.replace('question', '');
const answerSheetItem = document.querySelector(`#answerSheet${questionNumber}`);
if (answerSheetItem) {
answerSheetItem.classList.remove('active');
answerSheetItem.style.backgroundColor = '#fff';
answerSheetItem.style.color = '#6BA9FF';
}
}
}
// 切换题目标记状态
function toggleMarkQuestion(question, markButton) {
const questionId = question.getAttribute('id');
if (!questionId) return;
let marks = JSON.parse(localStorage.getItem('questionMarks') || '{}');
const isMarked = marks[questionId];
// 获取题号元素
const questionNumber = questionId.replace('question', '');
const answerSheetItem = document.querySelector(`#answerSheet${questionNumber}`);
if (isMarked) {
// 取消标记
delete marks[questionId];
markButton.textContent = '标记题目';
markButton.style.backgroundColor = '#fff';
markButton.style.color = '#666';
question.style.backgroundColor = '';
if (answerSheetItem) {
const markIcon = answerSheetItem.querySelector('.mark-icon');
if (markIcon) {
markIcon.remove();
}
}
} else {
// 添加标记
marks[questionId] = true;
markButton.textContent = '取消标记';
markButton.style.backgroundColor = '#FFA500';
markButton.style.color = '#fff';
question.style.backgroundColor = '#FFF3E0';
if (answerSheetItem) {
// 添加标记图标
if (!answerSheetItem.querySelector('.mark-icon')) {
const markIcon = document.createElement('span');
markIcon.className = 'mark-icon';
markIcon.innerHTML = '★';
markIcon.style.color = '#FF4444';
answerSheetItem.appendChild(markIcon);
}
}
}
localStorage.setItem('questionMarks', JSON.stringify(marks));
}
// 清除所有标记
function clearAllMarks() {
if (confirm('确定要清除所有标记吗?')) {
// 清除localStorage中的标记
localStorage.removeItem('questionMarks');
// 移除所有标记图标和样式
document.querySelectorAll('.mark-icon').forEach(icon => icon.remove());
document.querySelectorAll('.questionLi').forEach(question => {
const markButton = question.querySelector('.custom-answer-buttons button:first-child');
if (markButton) {
markButton.textContent = '标记题目';
markButton.style.backgroundColor = '#fff';
markButton.style.color = '#666';
}
question.style.backgroundColor = '';
});
}
}
// 添加样式
const style = document.createElement('style');
style.textContent = `
/* 通用样式 */
.mark_letter li,
.custom-answer-buttons button,
.questionLi,
.topicNumber_list li {
transition: all 0.3s;
}
/* 按钮和选项样式 */
.custom-answer-buttons button:hover,
.clear-answers-button:hover {
opacity: 0.9;
}
.mark_letter li {
padding: 5px 10px;
border-radius: 3px;
cursor: pointer;
}
/* 隐藏元素 */
.questionLi .mark_answer,
.mark_answer .colorDeep.marginRight40.fl,
.mark_answer .element-invisible-hidden.colorDeep {
display: none !important;
}
/* 题号样式 */
.topicNumber_list li {
position: relative;
background-color: #fff !important;
color: #6BA9FF !important;
}
.topicNumber_list li.active {
background-color: #BFDAFF !important;
}
/* 标记图标样式 */
.mark-icon {
position: static;
display: inline;
margin-left: 2px;
font-size: inherit;
color: #FF4444 !important;
}
/* 清除按钮样式 */
.clear-answers-button:hover,
.clear-marks-button:hover {
opacity: 0.9;
}
.clear-answers-button:hover {
background-color: #d32f2f !important;
}
.clear-marks-button:hover {
background-color: #FF8C00 !important;
}
`;
document.head.appendChild(style);
// 页面加载完成后添加按钮
waitForElement('.questionLi', () => {
addAnswerButtons();
});
})();