Greasy Fork 支持简体中文。

本地答案答题助手

从本地文档检索答案并自动选中

// ==UserScript==
// @name         本地答案答题助手
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  从本地文档检索答案并自动选中
// @author       侯钰熙
// @match        *://*/*
// @icon         data:image/png;base64,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
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @require      https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js
// @require      https://unpkg.com/xlsx/dist/xlsx.full.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.0/mammoth.browser.min.js
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 初始化 PDF.js
    const pdfjsLib = window['pdfjs-dist/build/pdf'];
    pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';

    // 配置项
    const CONFIG = {
        // 题目选择器,根据实际网站调整
        questionSelector: '.subject-item .subject-question',
        // 选项选择器
        optionSelector: '.subject-item .subject-option input[type="radio"]',
        // 本地答案数据
        answers: {
            // 示例数据格式
            '题目1': '答案1',
            '题目2': '答案2'
        },
        autoAnswer: {
            enabled: false,
            delay: 2000,  // 答题延迟,单位毫秒
            skipNoAnswer: true,  // 是否跳过没有答案的题目
        },
        articleContent: '', // 存储文章内容
        matchThreshold: 0.8, // 文本相似度匹配阈值
        highlight: {
            color: 'rgba(255, 235, 59, 0.3)', // 黄色半透明
            borderColor: '#FFC107',
            currentQuestion: null // 存储当前题目元素
        },
        nextButtonSelector: '.next-btn, .submit-btn', // 下一题按钮选择器
    };

    // 添加控制面板样式
    GM_addStyle(`
        #answer-helper-panel {
            position: fixed;
            top: 20px;
            right: 20px;
            background: #ffffff;
            padding: 15px;
            border-radius: 12px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
            z-index: 9999;
            font-family: 'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            min-width: 240px;
            transition: all 0.3s ease;
        }

        #answer-helper-panel:hover {
            box-shadow: 0 6px 25px rgba(0, 0, 0, 0.15);
        }

        #answer-helper-panel h3 {
            margin: 0 0 15px 0;
            color: #333;
            font-size: 16px;
            font-weight: 600;
            text-align: center;
        }

        #answer-helper-panel input[type="file"] {
            display: none;
        }

        #answer-helper-panel .file-label {
            display: block;
            padding: 8px 12px;
            background: #f0f2f5;
            border-radius: 8px;
            color: #666;
            cursor: pointer;
            margin-bottom: 10px;
            text-align: center;
            transition: all 0.2s ease;
            font-size: 14px;
        }

        #answer-helper-panel .file-label:hover {
            background: #e6e8eb;
            color: #333;
        }

        #answer-helper-panel .file-name {
            font-size: 12px;
            color: #666;
            margin: 5px 0;
            text-align: center;
            word-break: break-all;
        }

        #answer-helper-panel button {
            width: 100%;
            padding: 8px 15px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s ease;
        }

        #answer-helper-panel button:hover {
            background: #43A047;
            transform: translateY(-1px);
        }

        #answer-helper-panel button:active {
            transform: translateY(1px);
        }

        #status {
            margin-top: 10px;
            padding: 8px;
            border-radius: 6px;
            background: #f5f5f5;
            font-size: 12px;
            color: #666;
            text-align: center;
            min-height: 20px;
        }

        .status-success {
            color: #4CAF50 !important;
            background: #E8F5E9 !important;
        }

        .status-error {
            color: #F44336 !important;
            background: #FFEBEE !important;
        }

        .status-loading {
            color: #2196F3 !important;
            background: #E3F2FD !important;
        }

        .control-group {
            display: flex;
            gap: 8px;
            margin-bottom: 10px;
        }

        .control-group button {
            flex: 1;
            min-width: 0;
            padding: 6px 8px;
        }

        .toggle-button {
            background: #FF9800 !important;
        }

        .toggle-button.active {
            background: #E65100 !important;
        }

        .setting-item {
            display: flex;
            align-items: center;
            margin: 8px 0;
            font-size: 12px;
            color: #666;
        }

        .setting-item input[type="checkbox"] {
            margin-right: 8px;
        }

        .setting-item input[type="number"] {
            width: 60px;
            padding: 2px 4px;
            margin-left: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }

        .question-highlight {
            position: relative;
            background-color: ${CONFIG.highlight.color} !important;
            border: 2px solid ${CONFIG.highlight.borderColor} !important;
            border-radius: 4px;
            transition: all 0.3s ease;
        }

        .question-highlight::before {
            content: '当前题目';
            position: absolute;
            top: -20px;
            left: 50%;
            transform: translateX(-50%);
            background: ${CONFIG.highlight.borderColor};
            color: #fff;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 12px;
            z-index: 1000;
        }
    `);

    // 创建控制面板
    function createPanel() {
        const panel = document.createElement('div');
        panel.id = 'answer-helper-panel';
        panel.innerHTML = `
            <h3>📚 本地答案答题助手 </h3>
            <label class="file-label" for="answer-file">
                选择答案文件
            </label>
            <input type="file" id="answer-file" accept=".txt,.json,.docx,.xlsx,.pdf">
            <div class="file-name"></div>
            <button id="load-answers">开始导入</button>

            <div style="margin: 15px 0; border-top: 1px solid #eee;"></div>

            <div class="control-group">
                <button id="toggle-auto" class="toggle-button">自动答题</button>
                <button id="next-question">下一题</button>
            </div>

            <div class="setting-item">
                <input type="checkbox" id="skip-no-answer" ${CONFIG.autoAnswer.skipNoAnswer ? 'checked' : ''}>
                <label for="skip-no-answer">未找到答案时自动跳过</label>
            </div>

            <div class="setting-item">
                <label for="answer-delay">答题延迟(秒)</label>
                <input type="number" id="answer-delay" min="0" max="10" step="0.5"
                    value="${CONFIG.autoAnswer.delay/1000}">
            </div>

            <div class="setting-item">
                <label for="highlight-color">高亮颜色</label>
                <input type="color" id="highlight-color" value="#FFEB3B">
                <input type="range" id="highlight-opacity" min="0" max="100" value="30">
                <span id="opacity-value">30%</span>
            </div>

            <div id="status"></div>
        `;
        document.body.appendChild(panel);

        // 文件选择事件
        const fileInput = panel.querySelector('#answer-file');
        const fileLabel = panel.querySelector('.file-label');
        const fileName = panel.querySelector('.file-name');

        fileInput.addEventListener('change', (e) => {
            if (e.target.files.length > 0) {
                fileName.textContent = e.target.files[0].name;
                fileLabel.textContent = '更换文件';
            } else {
                fileName.textContent = '';
                fileLabel.textContent = '选择答案文件';
            }
        });

        document.getElementById('load-answers').addEventListener('click', loadAnswersFromFile);

        // 添加控制事件监听
        const toggleButton = document.getElementById('toggle-auto');
        const nextButton = document.getElementById('next-question');
        const skipCheckbox = document.getElementById('skip-no-answer');
        const delayInput = document.getElementById('answer-delay');

        toggleButton.addEventListener('click', () => {
            CONFIG.autoAnswer.enabled = !CONFIG.autoAnswer.enabled;
            toggleButton.classList.toggle('active');
            toggleButton.textContent = CONFIG.autoAnswer.enabled ? '停止答题' : '自动答题';

            if (CONFIG.autoAnswer.enabled) {
                startAutoAnswer();
            }
        });

        nextButton.addEventListener('click', () => {
            clickNextQuestion();
        });

        skipCheckbox.addEventListener('change', (e) => {
            CONFIG.autoAnswer.skipNoAnswer = e.target.checked;
        });

        delayInput.addEventListener('change', (e) => {
            CONFIG.autoAnswer.delay = Math.max(0, parseFloat(e.target.value) * 1000);
        });

        // 添加高亮颜色设置事件
        const colorInput = document.getElementById('highlight-color');
        const opacityInput = document.getElementById('highlight-opacity');
        const opacityValue = document.getElementById('opacity-value');

        function updateHighlightColor() {
            const color = colorInput.value;
            const opacity = opacityInput.value / 100;
            CONFIG.highlight.color = `${color}${Math.round(opacity * 255).toString(16).padStart(2, '0')}`;
            CONFIG.highlight.borderColor = color;

            // 更新样式
            GM_addStyle(`
                .question-highlight {
                    background-color: ${CONFIG.highlight.color} !important;
                    border: 2px solid ${CONFIG.highlight.borderColor} !important;
                }
                .question-highlight::before {
                    background: ${CONFIG.highlight.borderColor};
                }
            `);

            // 如果当前有高亮的题目,刷新其样式
            if (CONFIG.highlight.currentQuestion) {
                CONFIG.highlight.currentQuestion.classList.remove('question-highlight');
                setTimeout(() => {
                    CONFIG.highlight.currentQuestion.classList.add('question-highlight');
                }, 0);
            }
        }

        colorInput.addEventListener('input', updateHighlightColor);
        opacityInput.addEventListener('input', () => {
            opacityValue.textContent = `${opacityInput.value}%`;
            updateHighlightColor();
        });
    }

    // 文件加载处理函数
    async function loadAnswersFromFile() {
        const fileInput = document.getElementById('answer-file');
        const file = fileInput.files[0];
        if (!file) {
            updateStatus('请选择文件', 'error');
            return;
        }

        updateStatus('正在解析文件...', 'loading');

        try {
            let answers = {};
            const fileExt = file.name.split('.').pop().toLowerCase();

            switch (fileExt) {
                case 'json':
                case 'txt':
                    answers = await parseTextFile(file);
                    break;
                case 'docx':
                    answers = await parseWordFile(file);
                    break;
                case 'xlsx':
                    answers = await parseExcelFile(file);
                    break;
                case 'pdf':
                    answers = await parsePDFFile(file);
                    break;
                default:
                    throw new Error('不支持的文件格式');
            }

            CONFIG.answers = answers;
            GM_setValue('answers', answers);
            updateStatus('答案加载成功 ✨', 'success');
            startAutoMatch();
        } catch (error) {
            updateStatus('文件解析错误: ' + error.message, 'error');
        }
    }

    // 解析文本文件(JSON/TXT)
    function parseTextFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => {
                try {
                    const content = e.target.result;
                    try {
                        // 尝试解析为JSON
                        const answers = JSON.parse(content);
                        resolve(answers);
                    } catch {
                        // 如果不是JSON,则作为文章内容处理
                        CONFIG.articleContent = content;
                        resolve({}); // 返回空对象,因为答案需要实时搜索
                    }
                } catch (error) {
                    reject(new Error('文件解析失败'));
                }
            };
            reader.onerror = () => reject(new Error('文件读取失败'));
            reader.readAsText(file);
        });
    }

    // 解析Word文件
    function parseWordFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                try {
                    const arrayBuffer = e.target.result;
                    const result = await mammoth.extractRawText({ arrayBuffer });
                    const text = result.value;

                    // 假设Word文档的格式是每行一个题目答案对,用制表符或特定分隔符分隔
                    const answers = {};
                    const lines = text.split('\n');
                    lines.forEach(line => {
                        const [question, answer] = line.split('\t');
                        if (question && answer) {
                            answers[question.trim()] = answer.trim();
                        }
                    });

                    resolve(answers);
                } catch (error) {
                    reject(new Error('Word文件解析失败'));
                }
            };
            reader.onerror = () => reject(new Error('文件读取失败'));
            reader.readAsArrayBuffer(file);
        });
    }

    // 解析Excel���件
    function parseExcelFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => {
                try {
                    const data = new Uint8Array(e.target.result);
                    const workbook = XLSX.read(data, { type: 'array' });
                    const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
                    const answers = {};

                    // 假设Excel的A列是题目,B列是答案
                    const jsonData = XLSX.utils.sheet_to_json(firstSheet, { header: ['question', 'answer'] });
                    jsonData.forEach(row => {
                        if (row.question && row.answer) {
                            answers[row.question.trim()] = row.answer.trim();
                        }
                    });

                    resolve(answers);
                } catch (error) {
                    reject(new Error('Excel文件解析失败'));
                }
            };
            reader.onerror = () => reject(new Error('文件读取失败'));
            reader.readAsArrayBuffer(file);
        });
    }

    // 解析PDF文件
    function parsePDFFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                try {
                    const typedArray = new Uint8Array(e.target.result);
                    const loadingTask = pdfjsLib.getDocument({ data: typedArray });

                    updateStatus('正在解析PDF...', 'loading');
                    const pdf = await loadingTask.promise;
                    const answers = {};
                    const numPages = pdf.numPages;

                    // 读取所有页面的文本
                    for (let i = 1; i <= numPages; i++) {
                        updateStatus(`正在解析第 ${i}/${numPages} 页...`, 'loading');
                        const page = await pdf.getPage(i);
                        const textContent = await page.getTextContent();
                        let pageText = '';

                        // 更好的文本提取逻辑
                        let lastY = null;
                        textContent.items.forEach(item => {
                            if (lastY !== item.transform[5]) {
                                pageText += '\n';
                                lastY = item.transform[5];
                            }
                            pageText += item.str + ' ';
                        });

                        // 处理每一行
                        const lines = pageText.split('\n').filter(line => line.trim());
                        lines.forEach(line => {
                            // 尝试多种分隔符
                            let parts = line.split(/[\t|||│||]/);
                            if (parts.length < 2) {
                                parts = line.split(/\s{2,}/); // 使用两个或更多空格作为分隔符
                            }

                            if (parts.length >= 2) {
                                const question = parts[0].trim();
                                const answer = parts[parts.length - 1].trim();
                                if (question && answer) {
                                    answers[question] = answer;
                                }
                            }
                        });
                    }

                    if (Object.keys(answers).length === 0) {
                        reject(new Error('未能从PDF中提取到答案数据'));
                    } else {
                        updateStatus('PDF解析完成', 'success');
                        resolve(answers);
                    }
                } catch (error) {
                    console.error('PDF解析错误:', error);
                    reject(new Error('PDF文件解析失败: ' + error.message));
                }
            };
            reader.onerror = () => reject(new Error('文件读取失败'));
            reader.readAsArrayBuffer(file);
        });
    }

    // 更新状态显示
    function updateStatus(message, type = 'normal') {
        const statusEl = document.getElementById('status');
        statusEl.textContent = message;

        // 移除所有状态类
        statusEl.classList.remove('status-success', 'status-error', 'status-loading');

        // 根据类型添加对应的状态类
        switch (type) {
            case 'success':
                statusEl.classList.add('status-success');
                break;
            case 'error':
                statusEl.classList.add('status-error');
                break;
            case 'loading':
                statusEl.classList.add('status-loading');
                break;
        }
    }

    // 添加高亮当前题目的函数
    function highlightCurrentQuestion(question) {
        // 移除之前的高亮
        if (CONFIG.highlight.currentQuestion) {
            CONFIG.highlight.currentQuestion.classList.remove('question-highlight');
        }

        // 添加新的高亮
        if (question) {
            question.classList.add('question-highlight');
            CONFIG.highlight.currentQuestion = question;

            // 滚动到当前题目
            question.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }
    }

    // 开始自动匹配答案
    async function startAutoMatch() {
        // 获取当前题目
        const questionItem = document.querySelector('.subject-item');
        if (!questionItem) return false;

        // 高亮当前题目
        highlightCurrentQuestion(questionItem);

        // 获取题目文本(去除分数等额外信息)
        const questionText = questionItem.querySelector('.subject-question')
            ?.textContent.trim()
            .replace(/(\d+分)/, '') // 移除分数提示
            .replace(/^\d+\.\s*/, '') // 移除题号
            .trim();

        if (!questionText) return false;

        // 先尝试精确匹配
        let answer = CONFIG.answers[questionText];
        if (answer) {
            return selectAnswer(answer, questionItem);
        }

        // 如果有文章内容,尝试从文章中查找答案
        if (CONFIG.articleContent) {
            const options = Array.from(questionItem.querySelectorAll('.subject-option'));
            if (!options.length) return false;

            // 获取问题上下文
            const context = findQuestionContext(questionText);

            // 计算每个选项在上下文中的相似度
            const optionScores = options.map(option => {
                const optionText = option.textContent.trim().replace(/^[A-Z]\./, '').trim();
                const score = calculateContextSimilarity(context, optionText);
                return { option, optionText, score };
            });

            // 获取最高分的选项
            const bestMatch = optionScores.reduce((best, current) => {
                return current.score > best.score ? current : best;
            }, { score: 0 });

            if (bestMatch.score >= CONFIG.matchThreshold) {
                const radioInput = bestMatch.option.querySelector('input[type="radio"]');
                if (radioInput) {
                    radioInput.click();
                    updateStatus(`已选中最佳匹配答案: ${bestMatch.optionText} (相似度: ${bestMatch.score.toFixed(2)})`, 'success');
                    return true;
                }
            }
        }

        updateStatus('未找到匹配的答案', 'error');
        return false;
    }

    // 查找问题上下文
    function findQuestionContext(question) {
        const normalizedContent = CONFIG.articleContent.replace(/\s+/g, '');
        const normalizedQuestion = question.replace(/\s+/g, '');

        // 在文章中查找问题相关内容
        let bestMatchIndex = -1;
        let bestMatchScore = 0;

        // 使用滑动窗口查找最相关的段落
        const windowSize = 100; // 上下文窗口大小
        for (let i = 0; i < normalizedContent.length - windowSize; i++) {
            const window = normalizedContent.slice(i, i + windowSize);
            const score = similarity(window, normalizedQuestion);
            if (score > bestMatchScore) {
                bestMatchScore = score;
                bestMatchIndex = i;
            }
        }

        if (bestMatchIndex >= 0) {
            // 返回最佳匹配位置的上下文
            const start = Math.max(0, bestMatchIndex - 50);
            const end = Math.min(normalizedContent.length, bestMatchIndex + windowSize + 50);
            return normalizedContent.slice(start, end);
        }

        return '';
    }

    // 计算选项在上下文中的相似度
    function calculateContextSimilarity(context, option) {
        if (!context || !option) return 0;

        // 将上下文分成小段落
        const segments = [];
        const segmentLength = option.length * 2;
        for (let i = 0; i < context.length - segmentLength; i += segmentLength / 2) {
            segments.push(context.slice(i, i + segmentLength));
        }

        // 计算选项与每个段落的相似度,取最高值
        return segments.reduce((maxScore, segment) => {
            const score = similarity(segment, option);
            return Math.max(maxScore, score);
        }, 0);
    }

    // 选择答案的辅助函数
    function selectAnswer(answer, questionItem) {
        const options = questionItem.querySelectorAll('.subject-option');
        for (const option of options) {
            const optionText = option.textContent.trim().replace(/^[A-Z]\./, '').trim();
            if (similarity(optionText, answer) >= CONFIG.matchThreshold) {
                const radioInput = option.querySelector('input[type="radio"]');
                if (radioInput) {
                    radioInput.click();
                    updateStatus(`已选中答案: ${answer}`, 'success');
                    return true;
                }
            }
        }
        return false;
    }

    // 添加自动答题相关函数
    function startAutoAnswer() {
        if (!CONFIG.autoAnswer.enabled) return;

        startAutoMatch().then(matched => {
            if (!matched && CONFIG.autoAnswer.skipNoAnswer) {
                updateStatus('未找到答案,准备跳过...', 'loading');
                setTimeout(() => {
                    clickNextQuestion();
                }, 1000);
            } else if (matched) {
                updateStatus('答题成功,等待下一题...', 'success');
                setTimeout(() => {
                    clickNextQuestion();
                    startAutoAnswer();
                }, CONFIG.autoAnswer.delay);
            } else {
                CONFIG.autoAnswer.enabled = false;
                document.getElementById('toggle-auto').classList.remove('active');
                document.getElementById('toggle-auto').textContent = '自动答题';
                updateStatus('自动答题已停止', 'error');
            }
        });
    }

    // 点击下一题按钮
    function clickNextQuestion() {
        // 移除当前高亮
        if (CONFIG.highlight.currentQuestion) {
            CONFIG.highlight.currentQuestion.classList.remove('question-highlight');
            CONFIG.highlight.currentQuestion = null;
        }

        // 查找下一题或提交按钮
        const nextButton = document.querySelector(CONFIG.nextButtonSelector);
        if (nextButton) {
            nextButton.click();

            // 等待新题目加载完成后高亮
            setTimeout(() => {
                const newQuestion = document.querySelector('.subject-item');
                if (newQuestion) {
                    highlightCurrentQuestion(newQuestion);
                }
            }, 500);
        } else {
            updateStatus('未找到下一题按钮', 'error');
            CONFIG.autoAnswer.enabled = false;
            document.getElementById('toggle-auto').classList.remove('active');
            document.getElementById('toggle-auto').textContent = '自动答题';
        }
    }

    // 初始化
    function init() {
        createPanel();
        // 从存储中恢复答案数据
        const savedAnswers = GM_getValue('answers');
        if (savedAnswers) {
            CONFIG.answers = savedAnswers;
            startAutoMatch();
        }
    }

    // 启动脚本
    init();
})();