Greasy Fork

Greasy Fork is available in English.

hyw自动答题助手

hyw自动答题脚本

当前为 2024-11-06 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         hyw自动答题助手
// @namespace    http://tampermonkey.net/
// @version      0.3.4
// @description  hyw自动答题脚本
// @author       小马
// @license MIT
// @match        https://hyw.shixizhi.huawei.com/*
// @grant        GM_addStyle
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @run-at       document-end
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
// ==/UserScript==

(function () {
    'use strict';

    let questionBank = [];

    // 添加面板样式
    GM_addStyle(`
        .answer-panel {
            position: fixed;
            top: 20px;
            right: 20px;
            background: white;
            padding: 15px;
            border: 1px solid #ccc;
            border-radius: 5px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            z-index: 2147483647;  /* 最大z-index值 */
            min-width: 200px;
            font-family: Arial, sans-serif;
            user-select: none;
            -webkit-user-select: none;
            -moz-user-select: none;
        }

        .answer-panel h3 {
            margin: 0 0 10px 0;
            padding: 0;
            font-size: 16px;
            color: #333;
        }

        .answer-panel select,
        .answer-panel input,
        .answer-panel button {
            margin: 5px 0;
            padding: 5px;
            width: 100%;
            box-sizing: border-box;
        }

        .answer-panel button {
            background: #007bff;
            color: white;
            border: none;
            border-radius: 3px;
            padding: 8px;
            margin: 5px 0;
            cursor: pointer;
        }

        .answer-panel button:hover {
            background: #0056b3;
        }

        #status {
            margin-top: 10px;
            color: #666;
            font-size: 14px;
            word-break: break-all;
        }

        /* 确保面板始终可见 */
        .answer-panel * {
            display: block;
            visibility: visible !important;
            opacity: 1 !important;
        }
    `);

    // 创建控制面板
    function createPanel() {
        try {
            // 先检查是否已存在面板
            const existingPanel = document.querySelector('.answer-panel');
            if (existingPanel) {
                existingPanel.remove();
            }

            const panel = document.createElement('div');
            panel.className = 'answer-panel';
            panel.innerHTML = `
                <div>
                    <h3>自动答题助手</h3>
                    <select id="examType">
                        <option value="security">保密考试</option>
                        <option value="functional">职能考试</option>
                    </select>
                    <input type="file" id="fileInput" accept=".xlsx,.xls">
                    <button id="startBtn">开始答题</button>
                    <button id="stopBtn">停止答题</button>
                    <div id="status">等待上传题库...</div>
                </div>
            `;

            // 确保面板被添加到 body 的最后
            document.body.appendChild(panel);

            // 添加拖拽相关变量
            let isDragging = false;
            let currentX;
            let currentY;
            let initialX;
            let initialY;
            let xOffset = 0;
            let yOffset = 0;

            // 拖拽开始
            function dragStart(e) {
                // 如果点击的是select、input或button元素,不启动拖拽
                if (e.target.tagName.toLowerCase() === 'select' ||
                    e.target.tagName.toLowerCase() === 'input' ||
                    e.target.tagName.toLowerCase() === 'button') {
                    return;
                }

                if (e.type === "mousedown") {
                    initialX = e.clientX - xOffset;
                    initialY = e.clientY - yOffset;
                } else if (e.type === "touchstart") {
                    initialX = e.touches[0].clientX - xOffset;
                    initialY = e.touches[0].clientY - yOffset;
                }

                if (e.target === panel || panel.contains(e.target)) {
                    isDragging = true;
                }
            }

            // 拖拽过程
            function drag(e) {
                if (isDragging) {
                    e.preventDefault();

                    if (e.type === "mousemove") {
                        currentX = e.clientX - initialX;
                        currentY = e.clientY - initialY;
                    } else if (e.type === "touchmove") {
                        currentX = e.touches[0].clientX - initialX;
                        currentY = e.touches[0].clientY - initialY;
                    }

                    xOffset = currentX;
                    yOffset = currentY;

                    setTranslate(currentX, currentY, panel);
                }
            }

            // 设置面板位置
            function setTranslate(xPos, yPos, el) {
                el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`;
            }

            // 拖拽结束
            function dragEnd() {
                initialX = currentX;
                initialY = currentY;
                isDragging = false;
            }

            // 添加拖拽事件监听
            panel.addEventListener('mousedown', dragStart, false);
            document.addEventListener('mousemove', drag, false);
            document.addEventListener('mouseup', dragEnd, false);

            panel.addEventListener('touchstart', dragStart, false);
            document.addEventListener('touchmove', drag, false);
            document.addEventListener('touchend', dragEnd, false);

            // 阻止select的mousedown事件冒泡
            document.getElementById('examType').addEventListener('mousedown', (e) => {
                e.stopPropagation();
            });

            // 原有的事件绑定
            document.getElementById('fileInput').addEventListener('change', (e) => {
                const file = e.target.files[0];
                if (file) processExcel(file);
            });

            document.getElementById('startBtn').addEventListener('click', startAutoAnswer);
            document.getElementById('stopBtn').addEventListener('click', stopAutoAnswer);
        } catch (error) {
            console.error('创建控制面板失败:', error);
            // 可以尝试使用更简单的备用面板
            try {
                const simplePanel = document.createElement('div');
                simplePanel.className = 'answer-panel';
                simplePanel.innerHTML = `
                    <div>
                        <h3>自动答题助手(简易版)</h3>
                        <input type="file" id="fileInput" accept=".xlsx,.xls">
                        <button id="startBtn">开始答题</button>
                        <button id="stopBtn">停止答题</button>
                        <div id="status">等待上传题库...</div>
                    </div>
                `;
                document.body.appendChild(simplePanel);
            } catch (backupError) {
                console.error('创建备用面板也失败:', backupError);
            }
        }
    }

    // 更新状态显示
    function updateStatus(message) {
        document.getElementById('status').textContent = message;
    }

    let isRunning = false;

    // 停止自动答题
    function stopAutoAnswer() {
        isRunning = false;
        updateStatus('已停止答题');
    }

    // 开始自动答题
    async function startAutoAnswer() {
        if (questionBank.length === 0) {
            updateStatus('请先上传题库!');
            return;
        }

        isRunning = true;
        updateStatus('开始自动答题...');

        while (isRunning) {
            try {
                const questionInfo = getCurrentQuestionInfo();
                if (!questionInfo.question) {
                    updateStatus('未检测到题目,可能已完成答题');
                    isRunning = false;
                    break;
                }

                console.log('当前题目:', questionInfo.question);

                const answerInfo = findAnswer(questionInfo.question);
                if (answerInfo) {
                    const selected = selectAnswer(answerInfo, questionInfo.isMultipleChoice);
                    if (selected) {
                        updateStatus(`已答题: ${questionInfo.question.substring(0, 20)}...`);
                        // 减少答题后的等待时间为500ms
                        await new Promise(resolve => setTimeout(resolve, 200));

                        if (!clickNext(true)) {
                            updateStatus('无法找到下一题按钮,停止答题');
                            isRunning = false;
                            break;
                        }
                    } else {
                        updateStatus('答案选择失败,标记存疑');
                        if (!clickNext(false)) break;
                    }
                } else {
                    updateStatus('未找到匹配答案,标记存疑');
                    if (!clickNext(false)) break;
                }

                // 减少题目之间的等待时间为500ms
                await new Promise(resolve => setTimeout(resolve, 200));

            } catch (error) {
                console.error('答题过程出错:', error);
                updateStatus('答题过程出错,已停止');
                isRunning = false;
                break;
            }
        }
    }

    // 处理Excel文件上传
    async function handleFileUpload(e) {
        const file = e.target.files[0];
        const reader = new FileReader();

        reader.onload = function (e) {
            const data = new Uint8Array(e.target.result);
            const workbook = XLSX.read(data, { type: 'array' });
            const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
            questionBank = XLSX.utils.sheet_to_json(firstSheet);
            document.getElementById('status').innerText = `已加载 ${questionBank.length} 道题目`;
        };

        reader.readAsArrayBuffer(file);
    }

    // 处理Excel数据结构
    function processExcel(file) {
        const reader = new FileReader();
        reader.onload = function (e) {
            const data = new Uint8Array(e.target.result);
            const workbook = XLSX.read(data, { type: 'array' });
            const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
            const jsonData = XLSX.utils.sheet_to_json(firstSheet);

            // 获取当前选择的考试类型
            const examType = document.getElementById('examType').value;

            // 根据不同的考试类型处理数据
            if (examType === 'security') {
                // 保密考试题库格式
                questionBank = jsonData.map(row => ({
                    sequence: row['序号'],
                    type: row['试题类别'],
                    questionId: row['试题类型'],
                    question: row['试题题目'],
                    options: row['选项'],
                    answer: row['正确答案']
                }));
            } else if (examType === 'functional') {
                // 职能考试题格式
                questionBank = jsonData.map(row => ({
                    sequence: row['题库'],
                    type: row['题型'],
                    questionId: '',
                    question: row['题目'],
                    options: `${row['选项A']}\n${row['选项B']}\n${row['选项C']}\n${row['选项D']}\n${row['选项E'] || ''}\n${row['选项F'] || ''}\n${row['选项G'] || ''}\n${row['选项H'] || ''}`.trim(),
                    answer: row['正确答案']
                }));
            }

            updateStatus(`已导入 ${questionBank.length} 道题目`);
        };
        reader.readAsArrayBuffer(file);
    }

    // 查找答案
    function findAnswer(currentQuestion) {
        // 直接查找匹配的题目,不做文本清理
        const matchedQuestion = questionBank.find(item => {
            return item.question.includes(currentQuestion) || currentQuestion.includes(item.question);
        });
        console.log('匹配题目:', matchedQuestion);
        if (matchedQuestion) {
            return {
                answer: matchedQuestion.answer,
                type: matchedQuestion.type // 返回题目类型,用于判断单选/多选
            };
        }
        return null;
    }

    // 获取当前题目信息
    function getCurrentQuestionInfo() {
        try {
            // 修改选择器以匹配实际DOM结构
            const questionElement = document.querySelector('.main-title .content');
            if (!questionElement) {
                console.log('未找到题目元素');
                return { question: '', isMultipleChoice: false };
            }

            const question = questionElement.textContent.trim();

            // 判断是否为多选题 - 检查题类型标签
            const typeElement = document.querySelector('.type-name');
            const isMultipleChoice = typeElement && typeElement.textContent.includes('多选题');

            return { question, isMultipleChoice };
        } catch (error) {
            console.error('获取题目信息出错:', error);
            return { question: '', isMultipleChoice: false };
        }
    }

    // 选择答案
    function selectAnswer(answerInfo, isMultipleChoice) {
        try {
            if (!answerInfo) return false;
            const { answer } = answerInfo;
            const options = document.querySelectorAll('.option-list-item');
            let selected = false;

            // 将答案字符串转换为字母数组
            const answers = answer.toUpperCase().split('');
            const optionLetters = ['A', 'B', 'C', 'D', 'E', 'F'];

            options.forEach((option, index) => {
                const currentLetter = optionLetters[index];
                if (answers.includes(currentLetter)) {
                    const input = isMultipleChoice ?
                        option.querySelector('input[type="checkbox"]') :
                        option.querySelector('input[type="radio"]');

                    if (input && !input.checked) {
                        // 使用现代的事件触发方式
                        input.click();
                        selected = true;
                    }
                }
            });

            return selected;
        } catch (error) {
            console.error('选择答案出错:', error);
            return false;
        }
    }

    // 点击下一题
    function clickNext(answered) {
        try {
            // 获取所有按钮
            const buttons = document.querySelectorAll('.subject-btns .subject-btn');
            let nextButton = null;

            // 遍历所有按钮找到"下一题"按钮
            for (const button of buttons) {
                if (button.textContent.trim() === '下一题') {
                    nextButton = button;
                    break;
                }
            }

            if (nextButton) {
                nextButton.click();
                return true;
            }
            return false;
        } catch (error) {
            console.error('点击下一题按钮出错:', error);
            return false;
        }
    }

    // 修改初始化部分
    function init() {
        // 等待页面完全加载
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => setTimeout(createPanel, 1000));
        } else {
            setTimeout(createPanel, 1000);
        }
    }

    // 使用 window.onload 确保所有资源都加载完成
    window.addEventListener('load', () => {
        setTimeout(init, 1000);
    });
})();