hyw自动答题助手

hyw自动答题脚本

  1. // ==UserScript==
  2. // @name hyw自动答题助手
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.5.4
  5. // @description hyw自动答题脚本
  6. // @author 小马
  7. // @license MIT
  8. // @match https://hyw.shixizhi.huawei.com/*
  9. // @grant GM_addStyle
  10. // @grant unsafeWindow
  11. // @grant GM_xmlhttpRequest
  12. // @run-at document-end
  13. // @require https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
  14. // ==/UserScript==
  15.  
  16. (function () {
  17. 'use strict';
  18.  
  19. let questionBank = [];
  20.  
  21. // 添加面板样式
  22. GM_addStyle(`
  23. .answer-panel {
  24. position: fixed;
  25. top: 500px;
  26. right: 500px;
  27. background: white;
  28. padding: 15px;
  29. border: 1px solid #ccc;
  30. border-radius: 5px;
  31. box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  32. z-index: 2147483647; /* 最大z-index值 */
  33. min-width: 200px;
  34. font-family: Arial, sans-serif;
  35. user-select: none;
  36. -webkit-user-select: none;
  37. -moz-user-select: none;
  38. }
  39.  
  40. .answer-panel h3 {
  41. margin: 0 0 10px 0;
  42. padding: 0;
  43. font-size: 16px;
  44. color: #333;
  45. }
  46.  
  47. .answer-panel select,
  48. .answer-panel input,
  49. .answer-panel button {
  50. margin: 5px 0;
  51. padding: 5px;
  52. width: 100%;
  53. box-sizing: border-box;
  54. }
  55.  
  56. .answer-panel button {
  57. background: #007bff;
  58. color: white;
  59. border: none;
  60. border-radius: 3px;
  61. padding: 8px;
  62. margin: 5px 0;
  63. cursor: pointer;
  64. }
  65.  
  66. .answer-panel button:hover {
  67. background: #0056b3;
  68. }
  69.  
  70. #status {
  71. margin-top: 10px;
  72. color: #666;
  73. font-size: 14px;
  74. word-break: break-all;
  75. }
  76.  
  77. /* 确保面板始终可见 */
  78. .answer-panel * {
  79. display: block;
  80. visibility: visible !important;
  81. opacity: 1 !important;
  82. }
  83. `);
  84.  
  85. // 创建控制面板
  86. function createPanel() {
  87. try {
  88. // 先检查是否已存在面板
  89. const existingPanel = document.querySelector('.answer-panel');
  90. if (existingPanel) {
  91. existingPanel.remove();
  92. }
  93.  
  94. const panel = document.createElement('div');
  95. panel.className = 'answer-panel';
  96. panel.innerHTML = `
  97. <div>
  98. <h3>自动答题助手</h3>
  99. <select id="examType">
  100. <option value="security">保密考试</option>
  101. <option value="functional">职能考试</option>
  102. <option value="shixizhi">应知应会考试</option>
  103. </select>
  104. <input type="file" id="fileInput" accept=".xlsx,.xls">
  105. <button id="startBtn">开始答题</button>
  106. <button id="stopBtn">停止答题</button>
  107. <div id="status">等待上传题库...</div>
  108. </div>
  109. `;
  110.  
  111. // 确保面板被添加到 body 的最后
  112. document.body.appendChild(panel);
  113.  
  114. // 添加拖拽相关变量
  115. let isDragging = false;
  116. let currentX;
  117. let currentY;
  118. let initialX;
  119. let initialY;
  120. let xOffset = 0;
  121. let yOffset = 0;
  122.  
  123. // 拖拽开始
  124. function dragStart(e) {
  125. // 如果点击的是select、input或button元素,不启动拖拽
  126. if (e.target.tagName.toLowerCase() === 'select' ||
  127. e.target.tagName.toLowerCase() === 'input' ||
  128. e.target.tagName.toLowerCase() === 'button') {
  129. return;
  130. }
  131.  
  132. if (e.type === "mousedown") {
  133. initialX = e.clientX - xOffset;
  134. initialY = e.clientY - yOffset;
  135. } else if (e.type === "touchstart") {
  136. initialX = e.touches[0].clientX - xOffset;
  137. initialY = e.touches[0].clientY - yOffset;
  138. }
  139.  
  140. if (e.target === panel || panel.contains(e.target)) {
  141. isDragging = true;
  142. }
  143. }
  144.  
  145. // 拖拽过程
  146. function drag(e) {
  147. if (isDragging) {
  148. e.preventDefault();
  149.  
  150. if (e.type === "mousemove") {
  151. currentX = e.clientX - initialX;
  152. currentY = e.clientY - initialY;
  153. } else if (e.type === "touchmove") {
  154. currentX = e.touches[0].clientX - initialX;
  155. currentY = e.touches[0].clientY - initialY;
  156. }
  157.  
  158. xOffset = currentX;
  159. yOffset = currentY;
  160.  
  161. setTranslate(currentX, currentY, panel);
  162. }
  163. }
  164.  
  165. // 设置面板位置
  166. function setTranslate(xPos, yPos, el) {
  167. el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`;
  168. }
  169.  
  170. // 拖拽结束
  171. function dragEnd() {
  172. initialX = currentX;
  173. initialY = currentY;
  174. isDragging = false;
  175. }
  176.  
  177. // 添加拖拽事件监听
  178. panel.addEventListener('mousedown', dragStart, false);
  179. document.addEventListener('mousemove', drag, false);
  180. document.addEventListener('mouseup', dragEnd, false);
  181.  
  182. panel.addEventListener('touchstart', dragStart, false);
  183. document.addEventListener('touchmove', drag, false);
  184. document.addEventListener('touchend', dragEnd, false);
  185.  
  186. // 阻止select的mousedown事件冒泡
  187. document.getElementById('examType').addEventListener('mousedown', (e) => {
  188. e.stopPropagation();
  189. });
  190.  
  191. // 原有的事件绑定
  192. document.getElementById('fileInput').addEventListener('change', (e) => {
  193. const file = e.target.files[0];
  194. if (file) processExcel(file);
  195. });
  196.  
  197. document.getElementById('startBtn').addEventListener('click', startAutoAnswer);
  198. document.getElementById('stopBtn').addEventListener('click', stopAutoAnswer);
  199. } catch (error) {
  200. // 可以尝试使用更简单的备用面板
  201. try {
  202. const simplePanel = document.createElement('div');
  203. simplePanel.className = 'answer-panel';
  204. simplePanel.innerHTML = `
  205. <div>
  206. <h3>自动答题助手(简易版)</h3>
  207. <input type="file" id="fileInput" accept=".xlsx,.xls">
  208. <button id="startBtn">开始答题</button>
  209. <button id="stopBtn">停止答题</button>
  210. <div id="status">等待上传题库...</div>
  211. </div>
  212. `;
  213. document.body.appendChild(simplePanel);
  214. } catch (backupError) {
  215. }
  216. }
  217. }
  218.  
  219. // 更新状态显示
  220. function updateStatus(message) {
  221. document.getElementById('status').textContent = message;
  222. }
  223.  
  224. let isRunning = false;
  225.  
  226. // 停止自动答题
  227. function stopAutoAnswer() {
  228. isRunning = false;
  229. updateStatus('已停止答题');
  230. }
  231.  
  232. // 开始自动答题
  233. async function startAutoAnswer() {
  234. if (questionBank.length === 0) {
  235. updateStatus('请先上传题库!');
  236. return;
  237. }
  238.  
  239. isRunning = true;
  240. updateStatus('开始自动答题...');
  241.  
  242. while (isRunning) {
  243. try {
  244. const questionInfo = getCurrentQuestionInfo();
  245. if (!questionInfo.question) {
  246. updateStatus('未检测到题目,可能已完成答题');
  247. isRunning = false;
  248. break;
  249. }
  250.  
  251. console.log('当前题目:', questionInfo.question);
  252.  
  253. const answerInfo = findAnswer(questionInfo.question);
  254. if (answerInfo) {
  255. const selected = selectAnswer(answerInfo, questionInfo.isMultipleChoice);
  256. if (selected) {
  257. updateStatus(`已答题: ${questionInfo.question.substring(0, 20)}...`);
  258. // 减少答题后的等待时间为500ms
  259. await new Promise(resolve => setTimeout(resolve, 200));
  260.  
  261. if (!clickNext(true)) {
  262. updateStatus('无法找到下一题按钮,停止答题');
  263. isRunning = false;
  264. break;
  265. }
  266. } else {
  267. updateStatus('答案选择失败');
  268. if (!clickNext(false)) break;
  269. }
  270. } else {
  271. updateStatus('未找到匹配答案');
  272. if (!clickNext(false)) break;
  273. }
  274.  
  275. // 减少题目间的等待时间为500ms
  276. await new Promise(resolve => setTimeout(resolve, 200));
  277.  
  278. } catch (error) {
  279. updateStatus('答题过程出错,已停止');
  280. isRunning = false;
  281. break;
  282. }
  283. }
  284. }
  285.  
  286. // 处理Excel文件上传
  287. async function handleFileUpload(e) {
  288. const file = e.target.files[0];
  289. const reader = new FileReader();
  290.  
  291. reader.onload = function (e) {
  292. const data = new Uint8Array(e.target.result);
  293. const workbook = XLSX.read(data, { type: 'array' });
  294. const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
  295. questionBank = XLSX.utils.sheet_to_json(firstSheet);
  296. document.getElementById('status').innerText = `已加载 ${questionBank.length} 道题目`;
  297. };
  298.  
  299. reader.readAsArrayBuffer(file);
  300. }
  301.  
  302. // 处理Excel数据结构
  303. function processExcel(file) {
  304. const reader = new FileReader();
  305. reader.onload = function (e) {
  306. const data = new Uint8Array(e.target.result);
  307. const workbook = XLSX.read(data, { type: 'array' });
  308. const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
  309. const jsonData = XLSX.utils.sheet_to_json(firstSheet);
  310.  
  311. // 获取当前选择的考试类型
  312. const examType = document.getElementById('examType').value;
  313.  
  314. // 根据不同的考试类型处理数据
  315. if (examType === 'security') {
  316. // 保密考试题库格式
  317. questionBank = jsonData.map(row => ({
  318. sequence: row['序号'],
  319. type: row['试题类别'],
  320. questionId: row['试题类型'],
  321. question: row['试题题目'],
  322. options: row['选项'],
  323. answer: row['正确答案']
  324. }));
  325. } else if (examType === 'functional') {
  326. // 职能考试题格式
  327. questionBank = jsonData.map(row => ({
  328. sequence: row['题库'],
  329. type: row['题型'],
  330. questionId: '',
  331. question: row['题'],
  332. 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(),
  333. answer: row['正确答案']
  334. }));
  335. } else if (examType === 'shixizhi') {
  336. // 输出原始数据到控制台
  337. console.log('时习知原始数据:', jsonData);
  338.  
  339. // 时习知考试题库格式处理
  340. questionBank = jsonData.map(row => {
  341. // 跳过表头行
  342. if (row['序号'] === '序号') return null;
  343.  
  344. // 处理题目中的下划线
  345. let processedQuestion = row['__EMPTY'] || '';
  346. processedQuestion = processedQuestion
  347. // 统一下划线格式(将连续的下划线替换为5个下划线)
  348. .replace(/_{2,}/g, '_____')
  349. // 处理可能存在的特殊下划线字符
  350. .replace(/_/g, '_')
  351. // 处理下划线加空格的情况
  352. .replace(/_ /g, '_')
  353. .replace(/ _/g, '_');
  354.  
  355. return {
  356. sequence: row['序号'] || '',
  357. type: row['__EMPTY_3'] || '单选',
  358. questionId: '',
  359. question: processedQuestion,
  360. options: row['__EMPTY_1'] || '',
  361. answer: row['__EMPTY_2'] || '',
  362. originalQuestion: row['__EMPTY'] || ''
  363. };
  364. }).filter(item => item !== null);
  365.  
  366. // 输出处理后的题库到控制台
  367. console.log('时习知题库数据:', questionBank);
  368. updateStatus(`已导入 ${questionBank.length} 道题目`);
  369. }
  370.  
  371. updateStatus(`已导入 ${questionBank.length} 道题目`);
  372. };
  373. reader.readAsArrayBuffer(file);
  374. }
  375.  
  376. // 查找答案
  377. function findAnswer(currentQuestion) {
  378. try {
  379. if (!currentQuestion) {
  380. console.log('当前题目为空');
  381. return null;
  382. }
  383.  
  384. // 获取当前页面的所有选项文本
  385. const currentOptions = Array.from(document.querySelectorAll('.option-list-item'))
  386. .map(option => option.textContent.trim());
  387. console.log('当前页面选项:', currentOptions);
  388.  
  389. // 标准化当前题目
  390. let normalizedCurrentQuestion = currentQuestion
  391. .replace(/\s+/g, '') // 移除所有空格
  392. .replace(/()/g, '______') // 将括号替换为6个下划线
  393. .replace(/\(\)/g, '______') // 将英文括号替换为6个下划线
  394. .replace(/_+/g, '______'); // 将任意数量的下划线替换为6个下划线
  395.  
  396. console.log('标准化后的当前题目:', normalizedCurrentQuestion);
  397.  
  398. // 在题库中查找匹配的题目
  399. const matchedQuestions = questionBank.filter(item => {
  400. if (!item || !item.question) {
  401. console.log('题库中存在无效题目:', item);
  402. return false;
  403. }
  404.  
  405. // 标准化题库中的题目
  406. const normalizedItemQuestion = item.question
  407. .replace(/\s+/g, '') // 移除所有空格
  408. .replace(/_+/g, '______') // 将任意数量的下划线替换为6个下划线
  409. .replace(/。$/, ''); // 移除句尾句号
  410.  
  411. // 完全匹配比较
  412. if (normalizedCurrentQuestion === normalizedItemQuestion) {
  413. return true;
  414. }
  415.  
  416. // 移除标点符号后的模糊匹配
  417. const cleanCurrentQuestion = normalizedCurrentQuestion.replace(/[。,,]/g, '');
  418. const cleanItemQuestion = normalizedItemQuestion.replace(/[。,,]/g, '');
  419.  
  420. // 检查是否包含相同数量的填空
  421. const currentBlanks = (cleanCurrentQuestion.match(/______/g) || []).length;
  422. const itemBlanks = (cleanItemQuestion.match(/______/g) || []).length;
  423.  
  424. // 如果填空数量相同且文本相似,则认为是匹配的
  425. return currentBlanks === itemBlanks &&
  426. (cleanItemQuestion.includes(cleanCurrentQuestion) ||
  427. cleanCurrentQuestion.includes(cleanItemQuestion));
  428. });
  429.  
  430. console.log('匹配到的题目:', matchedQuestions);
  431.  
  432. if (matchedQuestions.length === 0) {
  433. return null;
  434. }
  435.  
  436. // 如果只有一个匹配项,验证必要属性后返回
  437. if (matchedQuestions.length === 1) {
  438. const question = matchedQuestions[0];
  439. if (!question.answer || !question.options) {
  440. console.log('匹配题目缺少必要属性:', question);
  441. return null;
  442. }
  443. return {
  444. answer: question.answer,
  445. type: question.type,
  446. options: question.options
  447. };
  448. }
  449.  
  450. // 如果有多个匹配项,通过比对选项找到最匹配的题目
  451. let bestMatch = null;
  452. let highestMatchScore = 0;
  453.  
  454. for (const question of matchedQuestions) {
  455. // 确保题目包含必要属性
  456. if (!question.options) {
  457. console.log('题目缺少选项:', question);
  458. continue;
  459. }
  460.  
  461. // 将题库中的选项按分隔符分割并清空
  462. const bankOptions = question.options.split(/[\n^]/)
  463. .map(opt => opt.trim())
  464. .filter(opt => opt)
  465. .map(opt => opt.replace(/^[A-Z]\s*[..、]\s*/, '').trim());
  466.  
  467. // 计算选项匹配分数
  468. let matchScore = 0;
  469. let matchedOptionsCount = 0;
  470.  
  471. // 对每个当前页面的选项进行匹配度计算
  472. for (const currentOpt of currentOptions) {
  473. const cleanCurrentOpt = currentOpt.replace(/^[A-Z]\s*[..、]\s*/, '').trim();
  474.  
  475. // 在题库选项中寻找最佳匹配
  476. const bestOptionMatch = bankOptions.find(bankOpt => {
  477. if (!bankOpt) return false;
  478. // 完全匹配得3分
  479. if (bankOpt === cleanCurrentOpt) {
  480. return true;
  481. }
  482. // 包含关系得2分
  483. if (bankOpt.includes(cleanCurrentOpt) || cleanCurrentOpt.includes(bankOpt)) {
  484. return true;
  485. }
  486. // 部分词语匹配得1分
  487. const bankWords = bankOpt.split(/\s+/);
  488. const currentWords = cleanCurrentOpt.split(/\s+/);
  489. return bankWords.some(word => currentWords.includes(word));
  490. });
  491.  
  492. if (bestOptionMatch) {
  493. matchedOptionsCount++;
  494. if (bestOptionMatch === cleanCurrentOpt) {
  495. matchScore += 3;
  496. } else if (bestOptionMatch.includes(cleanCurrentOpt) || cleanCurrentOpt.includes(bestOptionMatch)) {
  497. matchScore += 2;
  498. } else {
  499. matchScore += 1;
  500. }
  501. }
  502. }
  503.  
  504. // 计算最终匹配分数
  505. const finalScore = matchScore * (matchedOptionsCount / currentOptions.length);
  506.  
  507. // 更新最佳匹配
  508. if (finalScore > highestMatchScore) {
  509. highestMatchScore = finalScore;
  510. bestMatch = question;
  511. }
  512. }
  513.  
  514. // 如果找到了足够好的匹配(设置一个阈值)
  515. if (bestMatch && highestMatchScore >= currentOptions.length * 1.5) {
  516. if (!bestMatch.answer || !bestMatch.options) {
  517. console.log('最佳匹配题目缺少必要属性:', bestMatch);
  518. return null;
  519. }
  520. return {
  521. answer: bestMatch.answer,
  522. type: bestMatch.type,
  523. options: bestMatch.options
  524. };
  525. }
  526.  
  527. // 如果没有找到足够好的匹配,返回null
  528. return null;
  529.  
  530. } catch (error) {
  531. console.error('查找答案时出错:', error);
  532. return null;
  533. }
  534. }
  535.  
  536. // 获取当前题目信息
  537. function getCurrentQuestionInfo() {
  538. try {
  539. // 修改选择器以匹配实际DOM结构
  540. const questionElement = document.querySelector('.main-title .content');
  541. if (!questionElement) {
  542. console.log('未找到题目元素');
  543. return { question: '', isMultipleChoice: false };
  544. }
  545.  
  546. const question = questionElement.textContent.trim();
  547.  
  548. // 判断是否为多选题 - 检查题类型标签
  549. const typeElement = document.querySelector('.type-name');
  550. const isMultipleChoice = typeElement && typeElement.textContent.includes('多选题');
  551.  
  552. return { question, isMultipleChoice };
  553. } catch (error) {
  554. console.error('获取题目信息出错:', error);
  555. return { question: '', isMultipleChoice: false };
  556. }
  557. }
  558.  
  559. // 选择答案
  560. function selectAnswer(answerInfo, isMultipleChoice) {
  561. try {
  562. if (!answerInfo) return false;
  563. const options = document.querySelectorAll('.option-list-item');
  564. let selected = false;
  565. console.log('answerInfo:', answerInfo);
  566.  
  567. // 同时处理 ^ \n 分隔符
  568. const allOptions = answerInfo.options
  569. .split(/[\n^]/) // 使用正则表达式同时匹配\n和^
  570. .map(opt => opt.trim())
  571. .filter(opt => opt); // 过滤掉空字符串
  572.  
  573. console.log('allOptions', allOptions);
  574.  
  575. if (isMultipleChoice) {
  576. // 多选题处理:答案可能是多个字母组合(如"ABC")
  577. const correctAnswers = answerInfo.answer.split('').map(letter => {
  578. // 尝试在选项中找到以该字母开头的选项
  579. const matchedOption = allOptions.find((opt, index) => {
  580. // 如果选项没有字母前缀,则使用索引作为选项序号(A=0, B=1, 等)
  581. if (!opt.match(/^[A-Z]/)) {
  582. return index === (letter.charCodeAt(0) - 'A'.charCodeAt(0));
  583. }
  584. // 则匹配选项前缀
  585. return opt.startsWith(letter + '.') ||
  586. opt.startsWith(letter + '.') ||
  587. opt.startsWith(letter + '、') ||
  588. opt.startsWith(letter + ' 、') ||
  589. opt.match(new RegExp(`^${letter}\\s*[..、]`));
  590. });
  591. console.log('matchedOption', matchedOption);
  592.  
  593. return matchedOption;
  594. }).filter(Boolean);
  595.  
  596.  
  597.  
  598. // 遍历页面上的选项
  599. options.forEach((option, index) => {
  600. const optionText = option.textContent.trim();
  601. // 检查当前选项是否是正确答案之一
  602. const isCorrectOption = correctAnswers.some(correctAnswer => {
  603. // 如果正确答案没有字母前缀,直接比较内容
  604. const correctContent = correctAnswer.replace(/^[A-Z]\s*[..、]\s*/, '').trim();
  605. const cleanOptionText = optionText.replace(/^[A-Z]\s*[..、]\s*/, '').trim();
  606. return cleanOptionText === correctContent ||
  607. cleanOptionText.includes(correctContent) ||
  608. correctContent.includes(cleanOptionText);
  609. });
  610.  
  611. const input = option.querySelector('input[type="checkbox"]');
  612. if (input && isCorrectOption && !input.checked) {
  613. input.click();
  614. selected = true;
  615. }
  616. });
  617. } else {
  618. // 单选题处理
  619. let correctAnswerContent;
  620.  
  621. // 检查是否是标准的选项格式(A. B. C. 等)
  622. const hasStandardPrefix = allOptions.every(opt =>
  623. opt.match(/^[A-Z][..、\s]/) || // 匹配 A. A. A、 A [空格]
  624. opt.match(/^[A-Z][\s]*[..、]/) // 匹配 A . A . A 、
  625. );
  626.  
  627. if (!hasStandardPrefix) {
  628. // 如果不是标准格式,直接使用索引
  629. const index = answerInfo.answer.charCodeAt(0) - 'A'.charCodeAt(0);
  630. if (index >= 0 && index < allOptions.length) {
  631. correctAnswerContent = allOptions[index];
  632. console.log('根据索引找到的正确答案内容:', correctAnswerContent);
  633. }
  634. } else {
  635. // 如果是标准格式,查找匹配的选项
  636. correctAnswerContent = allOptions.find(opt =>
  637. opt.match(new RegExp(`^${answerInfo.answer}[..、\\s]`)) || // 匹配 A. A. A、 A [空格]
  638. opt.match(new RegExp(`^${answerInfo.answer}\\s*[..、]`)) // 匹配 A . A . A 、
  639. );
  640. }
  641.  
  642. if (!correctAnswerContent) {
  643. console.log('未找到正确答案内容');
  644. return false;
  645. }
  646.  
  647. // 清理选项内容时保留原始文本
  648. const cleanContent = (text) => {
  649. let cleanText = text;
  650. // 如果文本以标准选项格式开头,才移除前缀
  651. if (text.match(/^[A-Z][..、\s]/) || text.match(/^[A-Z][\s]*[..、]/)) {
  652. cleanText = text.replace(/^[A-Z]\s*[..、]\s*/, '').trim();
  653. }
  654. // 处理分号和空格
  655. return cleanText
  656. .replace(/[;;]/g, ' ') // 将中英文分号替换为空格
  657. .replace(/\s+/g, ' ') // 将多个空格合并为单个空格
  658. .trim(); // 移除首尾空格
  659. };
  660.  
  661. // 比较选项时使用清理后的内容
  662. options.forEach((option, index) => {
  663. const optionText = option.textContent.trim();
  664. const cleanOptionText = cleanContent(optionText);
  665. const cleanCorrectContent = cleanContent(correctAnswerContent);
  666.  
  667. console.log(`比较选项 ${index + 1}:`, {
  668. correctContent: cleanCorrectContent,
  669. cleanOptionText: cleanOptionText,
  670. isMatch: cleanOptionText === cleanCorrectContent
  671. });
  672.  
  673. // 只在完全相等时选中选项
  674. if (cleanOptionText === cleanCorrectContent) {
  675. const input = option.querySelector('input[type="radio"]');
  676. if (input && !input.checked) {
  677. console.log('找到完全匹配选项,点击选择');
  678. input.click();
  679. selected = true;
  680. }
  681. }
  682. });
  683. }
  684.  
  685. return selected;
  686. } catch (error) {
  687. console.error('选择答案出错:', error);
  688. return false;
  689. }
  690. }
  691.  
  692. // 点击下一题
  693. function clickNext(answered) {
  694. try {
  695. // 获取下一题按钮
  696. const nextButton = Array.from(document.querySelectorAll('.subject-btns .subject-btn'))
  697. .find(button => button.textContent.trim() === '下一题');
  698.  
  699. // 点击下一题按钮
  700. if (nextButton) {
  701. nextButton.click();
  702. return true;
  703. }
  704. return false;
  705. } catch (error) {
  706. console.error('点击下一题按钮出错:', error);
  707. return false;
  708. }
  709. }
  710.  
  711. // 修改初始化部分
  712. function init() {
  713. // 等待页面完全加载
  714. if (document.readyState === 'loading') {
  715. document.addEventListener('DOMContentLoaded', () => setTimeout(createPanel, 1000));
  716. } else {
  717. setTimeout(createPanel, 1000);
  718. }
  719. }
  720.  
  721. // 使用 window.onload 确保所有资源都加载完成
  722. window.addEventListener('load', () => {
  723. setTimeout(init, 1000);
  724. });
  725. })();
  726.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址