// ==UserScript==
// @name 【免费】深圳教师教育网测试题库
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 题库答案
// @author 伯乐
// @match https://www.0755tt.com/student/section*
// @grant GM_addStyle
// @grant GM_setClipboard
// @grant GM_getValue
// @grant GM_setValue
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// ==/UserScript==
(function() {
'use strict';
// 获取存储的位置
const savedPosition = GM_getValue('extractorPosition', { x: 20, y: 20 });
const savedSize = GM_getValue('extractorSize', { width: 400, height: 500 });
const isCollapsed = GM_getValue('extractorCollapsed', false);
// 添加样式
GM_addStyle(`
#question-extractor-btn {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 99999;
padding: 10px 15px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
transition: all 0.3s;
}
#question-extractor-btn:hover {
background-color: #45a049;
transform: scale(1.05);
}
#question-extractor-btn:active {
transform: scale(0.95);
}
#extractor-panel {
position: fixed;
top: ${savedPosition.y}px;
left: ${savedPosition.x}px;
width: ${savedSize.width}px;
height: ${savedSize.height}px;
background: white;
border-radius: 8px;
box-shadow: 0 0 15px rgba(0,0,0,0.3);
z-index: 99999;
display: ${isCollapsed ? 'none' : 'block'};
overflow: hidden;
font-family: 'Microsoft YaHei', sans-serif;
transition: all 0.3s;
}
#panel-header {
background: linear-gradient(to right, #3498db, #2980b9);
color: white;
padding: 8px 15px;
cursor: move;
display: flex;
justify-content: space-between;
align-items: center;
}
#panel-title {
font-weight: bold;
font-size: 16px;
}
#panel-controls {
display: flex;
gap: 8px;
}
.panel-btn {
width: 24px;
height: 24px;
border-radius: 50%;
background: rgba(255,255,255,0.3);
color: white;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
transition: all 0.2s;
}
.panel-btn:hover {
background: rgba(255,255,255,0.5);
}
#panel-content {
padding: 15px;
overflow-y: auto;
height: calc(100% - 60px);
}
.question-type-section {
margin-bottom: 20px;
}
.section-title {
background: #f1f1f1;
padding: 5px 10px;
border-left: 3px solid #3498db;
font-weight: bold;
margin-bottom: 10px;
font-size: 16px;
}
.question-item {
margin-bottom: 15px;
padding: 10px;
border-radius: 5px;
background: #f9f9f9;
transition: all 0.2s;
}
.question-item:hover {
background: #f0f7ff;
transform: translateX(5px);
}
.question-number {
font-weight: bold;
color: #2980b9;
margin-right: 5px;
}
.question-text {
margin-bottom: 8px;
line-height: 1.5;
}
.options {
margin-left: 20px;
margin-bottom: 8px;
}
.option {
margin: 4px 0;
line-height: 1.4;
}
.answer {
color: #e74c3c;
font-weight: bold;
margin-top: 5px;
padding-top: 5px;
border-top: 1px dashed #ddd;
}
#export-btn {
margin-top: 10px;
padding: 6px 12px;
background-color: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
width: 100%;
}
#export-btn:hover {
background-color: #2980b9;
}
#resizer {
position: absolute;
bottom: 0;
right: 0;
width: 20px;
height: 20px;
background: #3498db;
cursor: nwse-resize;
border-top-left-radius: 3px;
}
.dragging {
opacity: 0.9;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
}
`);
// 创建按钮
function createButton() {
const existingBtn = document.getElementById('question-extractor-btn');
if (existingBtn) existingBtn.remove();
const button = document.createElement('button');
button.id = 'question-extractor-btn';
button.innerHTML = '📚 题目答案';
document.body.appendChild(button);
button.addEventListener('click', togglePanel);
return button;
}
// 创建悬浮面板
function createPanel() {
const existingPanel = document.getElementById('extractor-panel');
if (existingPanel) existingPanel.remove();
const panel = document.createElement('div');
panel.id = 'extractor-panel';
panel.innerHTML = `
`;
document.body.appendChild(panel);
// 初始化拖拽功能
initDraggable();
// 初始化调整大小功能
initResizable();
// 初始化按钮事件
initControlButtons();
return panel;
}
// 初始化拖拽功能
function initDraggable() {
const panel = document.getElementById('extractor-panel');
const header = document.getElementById('panel-header');
let isDragging = false;
let offsetX, offsetY;
header.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - panel.getBoundingClientRect().left;
offsetY = e.clientY - panel.getBoundingClientRect().top;
panel.classList.add('dragging');
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const x = e.clientX - offsetX;
const y = e.clientY - offsetY;
// 限制在视窗内
const maxWidth = window.innerWidth - panel.offsetWidth;
const maxHeight = window.innerHeight - panel.offsetHeight;
panel.style.left = Math.max(0, Math.min(x, maxWidth)) + 'px';
panel.style.top = Math.max(0, Math.min(y, maxHeight)) + 'px';
});
document.addEventListener('mouseup', () => {
if (isDragging) {
isDragging = false;
panel.classList.remove('dragging');
// 保存位置
const rect = panel.getBoundingClientRect();
GM_setValue('extractorPosition', {
x: rect.left,
y: rect.top
});
}
});
}
// 初始化调整大小功能
function initResizable() {
const panel = document.getElementById('extractor-panel');
const resizer = document.getElementById('resizer');
let isResizing = false;
resizer.addEventListener('mousedown', (e) => {
isResizing = true;
document.body.style.cursor = 'nwse-resize';
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isResizing) return;
const rect = panel.getBoundingClientRect();
const width = e.clientX - rect.left;
const height = e.clientY - rect.top;
// 限制最小尺寸
panel.style.width = Math.max(300, width) + 'px';
panel.style.height = Math.max(300, height) + 'px';
});
document.addEventListener('mouseup', () => {
if (isResizing) {
isResizing = false;
document.body.style.cursor = 'default';
// 保存尺寸
const rect = panel.getBoundingClientRect();
GM_setValue('extractorSize', {
width: rect.width,
height: rect.height
});
}
});
}
// 初始化控制按钮
function initControlButtons() {
document.getElementById('close-btn').addEventListener('click', () => {
document.getElementById('extractor-panel').style.display = 'none';
GM_setValue('extractorCollapsed', true);
});
document.getElementById('minimize-btn').addEventListener('click', togglePanel);
}
// 切换面板显示/隐藏
function togglePanel() {
const panel = document.getElementById('extractor-panel');
const isHidden = panel.style.display === 'none';
panel.style.display = isHidden ? 'block' : 'none';
GM_setValue('extractorCollapsed', !isHidden);
// 更新按钮文本
const btn = document.getElementById('question-extractor-btn');
btn.innerHTML = isHidden ? '📚 题目答案' : '◀ 展开';
}
// 拦截XHR获取题目数据
function interceptXHR() {
const open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
if (url.includes('/api/exam/start') || url.includes('/api/exam/answer') || url.includes('paperId') || url.includes('test')) {
this.addEventListener('load', function() {
try {
const response = JSON.parse(this.responseText);
if (response.code === 200 && response.data && response.data.questions) {
storeAndRenderQuestions(response.data);
}
} catch (e) {
console.error('获取题目失败:', e);
}
});
}
open.apply(this, arguments);
};
}
// 存储并渲染题目
function storeAndRenderQuestions(data) {
window.examData = data;
renderQuestions(data);
}
// 按题型分组题目
function groupQuestionsByType(questions) {
const groups = {
'judgment': [], // 判断题 type=1
'single': [], // 单选题 type=2
'multiple': [] // 多选题 type=3
};
questions.forEach(q => {
if (q.type === "1") {
groups.judgment.push(q);
} else if (q.type === "2") {
groups.single.push(q);
} else if (q.type === "3") {
groups.multiple.push(q);
}
});
return groups;
}
// 格式化答案文本
function formatAnswer(q) {
if (q.type === "1") {
return q.answer === "T" ? "【答案】正确" : "【答案】错误";
} else if (q.type === "2") {
return `【答案】${q.answer}`;
} else if (q.type === "3") {
return `【答案】${q.answer.split(',').join(', ')}`;
}
return `【答案】${q.answer}`;
}
// 渲染题目 - 修改了题型排序顺序
function renderQuestions(data) {
const panelContent = document.getElementById('panel-content');
if (!panelContent) return;
// 按题型分组
const grouped = groupQuestionsByType(data.questions);
// 构建HTML
let html = '';
// 课程信息
html += `
课程: ${data.paper.courseName || '未命名课程'}
章节: ${data.paper.chapterName || '未命名章节'}
测试: ${data.paper.paperName || '未命名测试'}
`;
// 单选题
if (grouped.single.length > 0) {
html += `
◉ 单选题 (${grouped.single.length}题)
`;
grouped.single.forEach((q, index) => {
html += `
${index + 1}.${q.question}
`;
if (q.options && q.options.length > 0) {
html += `
`;
q.options.forEach(opt => {
html += `
${opt.option}. ${opt.content}
`;
});
html += `
`;
}
html += `
${formatAnswer(q)}
`;
});
html += `
`;
}
// 多选题
if (grouped.multiple.length > 0) {
html += `
◉ 多选题 (${grouped.multiple.length}题)
`;
grouped.multiple.forEach((q, index) => {
html += `
${index + 1}.${q.question}
`;
if (q.options && q.options.length > 0) {
html += `
`;
q.options.forEach(opt => {
html += `
${opt.option}. ${opt.content}
`;
});
html += `
`;
}
html += `
${formatAnswer(q)}
`;
});
html += `
`;
}
// 判断题
if (grouped.judgment.length > 0) {
html += `
◉ 判断题 (${grouped.judgment.length}题)
`;
grouped.judgment.forEach((q, index) => {
html += `
${index + 1}.${q.question}
${formatAnswer(q)}
`;
});
html += `
`;
}
// 添加导出按钮
html += ``;
panelContent.innerHTML = html;
// 添加导出按钮事件
document.getElementById('export-btn').addEventListener('click', exportAsText);
}
// 导出为文本
function exportAsText() {
if (!window.examData) {
alert('没有可导出的题目数据');
return;
}
const grouped = groupQuestionsByType(window.examData.questions);
let text = '';
// 课程信息
text += `课程: ${window.examData.paper.courseName || '未命名课程'}\n`;
text += `章节: ${window.examData.paper.chapterName || '未命名章节'}\n`;
text += `测试: ${window.examData.paper.paperName || '未命名测试'}\n\n`;
// 单选题
if (grouped.single.length > 0) {
text += `◉ 单选题 (${grouped.single.length}题)\n`;
grouped.single.forEach((q, index) => {
text += `${index + 1}. ${q.question}\n`;
if (q.options && q.options.length > 0) {
q.options.forEach(opt => {
text += ` ${opt.option}. ${opt.content}\n`;
});
}
text += `${formatAnswer(q).replace('【答案】', '答案: ')}\n\n`;
});
}
// 多选题
if (grouped.multiple.length > 0) {
text += `\n◉ 多选题 (${grouped.multiple.length}题)\n`;
grouped.multiple.forEach((q, index) => {
text += `${index + 1}. ${q.question}\n`;
if (q.options && q.options.length > 0) {
q.options.forEach(opt => {
text += ` ${opt.option}. ${opt.content}\n`;
});
}
text += `${formatAnswer(q).replace('【答案】', '答案: ')}\n\n`;
});
}
// 判断题
if (grouped.judgment.length > 0) {
text += `\n◉ 判断题 (${grouped.judgment.length}题)\n`;
grouped.judgment.forEach((q, index) => {
text += `${index + 1}. ${q.question}\n`;
text += `${formatAnswer(q).replace('【答案】', '答案: ')}\n\n`;
});
}
// 复制到剪贴板
if (GM_setClipboard) {
GM_setClipboard(text);
alert('题目内容已复制到剪贴板!');
} else {
alert('请手动复制以下内容:\n\n' + text);
}
}
// 初始化
function init() {
createButton();
createPanel();
interceptXHR();
// 检查是否有已存储的题目数据
if (window.examData) {
renderQuestions(window.examData);
}
}
// 页面加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();