// ==UserScript==
// @name hyw自动答题助手
// @namespace http://tampermonkey.net/
// @version 0.2
// @description hyw自动答题脚本
// @license MIT
// @author 小马
// @match https://hyw.shixizhi.huawei.com/iexam/*/examContent*
// @grant GM_addStyle
// @require https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
// @downloadURL none
// ==/UserScript==
(function () {
'use strict';
let questionBank = [];
// 添加面板样式
GM_addStyle(`
.answer-panel {
position: fixed;
top: 60px;
right: 20px;
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
z-index: 9999;
font-size: 14px;
cursor: move;
user-select: none;
}
.answer-panel input[type="file"] {
margin-bottom: 10px;
}
.answer-panel button {
margin: 5px;
padding: 5px 10px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.answer-panel button:hover {
background: #0056b3;
}
#status {
margin-top: 10px;
color: #666;
}
`);
// 创建控制面板
function createPanel() {
const panel = document.createElement('div');
panel.className = 'answer-panel';
panel.innerHTML = `
`;
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);
}
// 更新状态显示
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;
// 将答案字符串转换为字母数组
// 例如: 'ABCD' => ['A', 'B', 'C', 'D']
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;
}
}
// 初始化
createPanel();
})();