Greasy Fork

Greasy Fork is available in English.

本地答案答题助手

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

当前为 2024-12-26 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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();
})();