您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
此脚本受版权专利保护,禁止未经授权的修改和分发,否则负法律责任
// ==UserScript== // @name 阿西吧抢终极 // @namespace http://tampermonkey.net/ // @version 1.0.2 // @description 此脚本受版权专利保护,禁止未经授权的修改和分发,否则负法律责任 // @author 晓星翼翼 // @license All Rights Reserved // @copyright 2025, 晓星翼翼 // @match https://docs.qq.com/form/* // @grant GM_setValue // @grant GM_getValue // ==/UserScript== (function() { 'use strict'; // 从存储中获取个人信息,如果不存在则使用默认值 let myInfo = { name: GM_getValue('userInfo_name', ''), gradeClass: GM_getValue('userInfo_gradeClass', ''), contact: GM_getValue('userInfo_contact', ''), volunteerId: GM_getValue('userInfo_volunteerId', '') }; const hashedKey = '413c05ba9f2feb8109e371acd4dc0f257d150376a8fd6dba427cfc15ad56636c'; const keyExpiration = 4320 * 60 * 60 * 1000; let hasFilledForm = false; let autoSubmitEnabled = GM_getValue('autoSubmitEnabled', false); let autoFillEnabled = GM_getValue('autoFillEnabled', true); let keyVerified = false; let lastVerificationTime = GM_getValue('lastVerificationTime', 0); let userInfoSet = GM_getValue('userInfoSet', false); // 延迟设置(单位:秒) let delaySettings = { fillDelay: GM_getValue('delay_fillDelay', 0.1), // 填写字段间隔 submitDelay: GM_getValue('delay_submitDelay', 0.1), // 提交前等待 confirmDelay: GM_getValue('delay_confirmDelay', 0.1) // 确认按钮点击延迟 }; function sha256(message) { const encoder = new TextEncoder(); const data = encoder.encode(message); return crypto.subtle.digest('SHA-256', data) .then(hash => { return Array.from(new Uint8Array(hash)) .map(b => b.toString(16).padStart(2, '0')) .join(''); }); } function checkKeyValidity() { const now = Date.now(); if (lastVerificationTime && (now - lastVerificationTime < keyExpiration)) { keyVerified = true; return true; } return false; } function checkUserInfo() { return userInfoSet && myInfo.name && myInfo.gradeClass && myInfo.contact && myInfo.volunteerId; } function createDelayDialog() { const existingDialog = document.getElementById('delaySettingsDialog'); if (existingDialog) { existingDialog.remove(); } const dialog = document.createElement('div'); dialog.id = 'delaySettingsDialog'; dialog.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; border: 1px solid #ccc; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.3); z-index: 10000; width: 400px; font-family: Arial, sans-serif; `; dialog.innerHTML = ` <h3 style="margin-top: 0; color: #333;">延迟时间设置</h3> <p style="color: #666; font-size: 14px;">请合理设置时间,不要太离谱了</p> <div style="margin: 15px 0;"> <label style="display: block; margin-bottom: 5px; color: #333; font-size: 14px;">填写字段间隔 (秒):</label> <input type="number" id="fillDelayInput" value="${delaySettings.fillDelay}" min="0.05" max="10" step="0.05" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;"> <small style="color: #999;">建议: 0.1-0.3秒,填写每个字段之间的等待时间</small> </div> <div style="margin: 15px 0;"> <label style="display: block; margin-bottom: 5px; color: #333; font-size: 14px;">提交前等待 (秒):</label> <input type="number" id="submitDelayInput" value="${delaySettings.submitDelay}" min="0.1" max="20" step="0.1" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;"> <small style="color: #999;">建议: 0.2-0.5秒,填写完成后到提交的等待时间</small> </div> <div style="margin: 15px 0;"> <label style="display: block; margin-bottom: 5px; color: #333; font-size: 14px;">确认按钮延迟 (秒):</label> <input type="number" id="confirmDelayInput" value="${delaySettings.confirmDelay}" min="0.05" max="5" step="0.05" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;"> <small style="color: #999;">建议: 0.1-0.2秒,点击提交到确认之间的延迟</small> </div> <div style="background: #f8f9fa; padding: 10px; border-radius: 3px; margin: 15px 0; font-size: 12px; color: #666;"> <strong>预设方案:</strong><br> <button id="fastPreset" style="margin: 2px; padding: 3px 8px; font-size: 11px; background: #17a2b8; color: white; border: none; border-radius: 2px; cursor: pointer;">极速 (0.05,0.1,0.05)</button> <button id="normalPreset" style="margin: 2px; padding: 3px 8px; font-size: 11px; background: #28a745; color: white; border: none; border-radius: 2px; cursor: pointer;">正常 (0.2,0.3,0.1)</button> <button id="slowPreset" style="margin: 2px; padding: 3px 8px; font-size: 11px; background: #ffc107; color: black; border: none; border-radius: 2px; cursor: pointer;">缓慢 (0.5,1,0.5)</button> <button id="randomPreset" style="margin: 2px; padding: 3px 8px; font-size: 11px; background: #6f42c1; color: white; border: none; border-radius: 2px; cursor: pointer;">随机化</button> </div> <div style="text-align: right; margin-top: 20px;"> <button id="cancelDelayButton" style="background: #f5f5f5; border: 1px solid #ddd; padding: 8px 16px; margin-right: 10px; border-radius: 3px; cursor: pointer;">取消</button> <button id="saveDelayButton" style="background: #4285f4; color: white; border: none; padding: 8px 16px; border-radius: 3px; cursor: pointer;">保存</button> </div> `; document.body.appendChild(dialog); // 添加背景遮罩 const overlay = document.createElement('div'); overlay.id = 'delayDialogOverlay'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; `; document.body.appendChild(overlay); // 预设方案事件 document.getElementById('fastPreset').addEventListener('click', () => { document.getElementById('fillDelayInput').value = '0.05'; document.getElementById('submitDelayInput').value = '0.1'; document.getElementById('confirmDelayInput').value = '0.05'; }); document.getElementById('normalPreset').addEventListener('click', () => { document.getElementById('fillDelayInput').value = '0.2'; document.getElementById('submitDelayInput').value = '0.3'; document.getElementById('confirmDelayInput').value = '0.1'; }); document.getElementById('slowPreset').addEventListener('click', () => { document.getElementById('fillDelayInput').value = '0.5'; document.getElementById('submitDelayInput').value = '1.0'; document.getElementById('confirmDelayInput').value = '0.5'; }); document.getElementById('randomPreset').addEventListener('click', () => { document.getElementById('fillDelayInput').value = (0.1 + Math.random() * 0.4).toFixed(2); document.getElementById('submitDelayInput').value = (0.2 + Math.random() * 0.6).toFixed(2); document.getElementById('confirmDelayInput').value = (0.05 + Math.random() * 0.15).toFixed(2); }); document.getElementById('cancelDelayButton').addEventListener('click', () => { dialog.remove(); overlay.remove(); }); document.getElementById('saveDelayButton').addEventListener('click', saveDelaySettings); } // 保存延迟设置 function saveDelaySettings() { const fillDelay = parseFloat(document.getElementById('fillDelayInput').value); const submitDelay = parseFloat(document.getElementById('submitDelayInput').value); const confirmDelay = parseFloat(document.getElementById('confirmDelayInput').value); delaySettings = { fillDelay, submitDelay, confirmDelay }; GM_setValue('delay_fillDelay', fillDelay); GM_setValue('delay_submitDelay', submitDelay); GM_setValue('delay_confirmDelay', confirmDelay); document.getElementById('delaySettingsDialog').remove(); const overlay = document.getElementById('delayDialogOverlay'); if (overlay) overlay.remove(); updateStatus(`延迟设置已保存:填写${fillDelay}s,提交${submitDelay}s,确认${confirmDelay}s`, true); } function createInfoDialog(isFirstTime = false) { const existingDialog = document.getElementById('userInfoDialog'); if (existingDialog) { existingDialog.remove(); } const dialog = document.createElement('div'); dialog.id = 'userInfoDialog'; dialog.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; border: 1px solid #ccc; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.3); z-index: 10000; width: 400px; font-family: Arial, sans-serif; max-height: 80vh; overflow-y: auto; `; dialog.innerHTML = ` <h3 style="margin-top: 0; color: #333;">${isFirstTime ? '首次设置个人信息' : '修改个人信息'}</h3> <p style="color: #666; font-size: 14px;">请输入您的详细信息,这些信息仅用于自动填写表单</p> <div style="margin: 15px 0;"> <label style="display: block; margin-bottom: 5px; color: #333; font-size: 14px;">姓名:</label> <input type="text" id="nameInput" value="${myInfo.name}" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;" placeholder="请输入您的姓名"> </div> <div style="margin: 15px 0;"> <label style="display: block; margin-bottom: 5px; color: #333; font-size: 14px;">年级班级:</label> <input type="text" id="gradeClassInput" value="${myInfo.gradeClass}" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;" placeholder="例如:2023级计算机1班"> </div> <div style="margin: 15px 0;"> <label style="display: block; margin-bottom: 5px; color: #333; font-size: 14px;">联系方式:</label> <input type="text" id="contactInput" value="${myInfo.contact}" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;" placeholder="手机号码或QQ号"> </div> <div style="margin: 15px 0;"> <label style="display: block; margin-bottom: 5px; color: #333; font-size: 14px;">志愿者编号:</label> <input type="text" id="volunteerIdInput" value="${myInfo.volunteerId}" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;" placeholder="请输入志愿者编号"> </div> <div style="text-align: right; margin-top: 20px;"> ${!isFirstTime ? '<button id="cancelInfoButton" style="background: #f5f5f5; border: 1px solid #ddd; padding: 8px 16px; margin-right: 10px; border-radius: 3px; cursor: pointer;">取消</button>' : ''} <button id="saveInfoButton" style="background: #4285f4; color: white; border: none; padding: 8px 16px; border-radius: 3px; cursor: pointer;">保存</button> </div> <p id="infoError" style="color: red; font-size: 12px; margin-top: 10px; display: none;">请填写完整的信息</p> `; document.body.appendChild(dialog); // 添加背景遮罩 const overlay = document.createElement('div'); overlay.id = 'infoDialogOverlay'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; `; document.body.appendChild(overlay); // 绑定事件 if (!isFirstTime) { document.getElementById('cancelInfoButton').addEventListener('click', () => { dialog.remove(); overlay.remove(); }); } document.getElementById('saveInfoButton').addEventListener('click', () => saveUserInfo(isFirstTime)); // 回车保存 [document.getElementById('nameInput'), document.getElementById('gradeClassInput'), document.getElementById('contactInput'), document.getElementById('volunteerIdInput')].forEach(input => { input.addEventListener('keypress', (e) => { if (e.key === 'Enter') { saveUserInfo(isFirstTime); } }); }); setTimeout(() => { document.getElementById('nameInput').focus(); }, 100); } // 保存用户信息 function saveUserInfo(isFirstTime = false) { const nameInput = document.getElementById('nameInput'); const gradeClassInput = document.getElementById('gradeClassInput'); const contactInput = document.getElementById('contactInput'); const volunteerIdInput = document.getElementById('volunteerIdInput'); const errorMsg = document.getElementById('infoError'); const name = nameInput.value.trim(); const gradeClass = gradeClassInput.value.trim(); const contact = contactInput.value.trim(); const volunteerId = volunteerIdInput.value.trim(); // 验证必填字段 if (!name || !gradeClass || !contact || !volunteerId) { errorMsg.style.display = 'block'; return; } // 保存信息 myInfo = { name, gradeClass, contact, volunteerId }; GM_setValue('userInfo_name', name); GM_setValue('userInfo_gradeClass', gradeClass); GM_setValue('userInfo_contact', contact); GM_setValue('userInfo_volunteerId', volunteerId); GM_setValue('userInfoSet', true); userInfoSet = true; // 关闭对话框 document.getElementById('userInfoDialog').remove(); const overlay = document.getElementById('infoDialogOverlay'); if (overlay) overlay.remove(); // 显示成功消息 updateStatus(`信息已保存:${name} - ${gradeClass}`, true); // 如果是首次设置,继续初始化流程 if (isFirstTime) { setTimeout(() => { if (checkKeyValidity()) { init(); addControlButtons(); } else { createKeyDialog(); } }, 1000); } else { // 重置填写状态,允许重新填写 hasFilledForm = false; } } function createKeyDialog() { const existingDialog = document.getElementById('keyVerificationDialog'); if (existingDialog) { existingDialog.remove(); } const dialog = document.createElement('div'); dialog.id = 'keyVerificationDialog'; dialog.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; border: 1px solid #ccc; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.3); z-index: 10000; width: 300px; font-family: Arial, sans-serif; `; dialog.innerHTML = ` <h3 style="margin-top: 0; color: #333;">请输入密钥</h3> <p style="color: #666; font-size: 14px;">请输入正确的密钥以打开新世界大门</p> <input type="password" id="keyInput" style="width: 100%; padding: 8px; margin: 10px 0; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box;"> <div style="text-align: right;"> <button id="cancelKeyButton" style="background: #f5f5f5; border: 1px solid #ddd; padding: 5px 10px; margin-right: 10px; border-radius: 3px; cursor: pointer;">取消</button> <button id="submitKeyButton" style="background: #4285f4; color: white; border: none; padding: 5px 10px; border-radius: 3px; cursor: pointer;">确认</button> </div> <p id="keyError" style="color: red; font-size: 12px; margin-top: 10px; display: none;">密码错误,请重新输入</p> `; document.body.appendChild(dialog); // 添加背景遮罩 const overlay = document.createElement('div'); overlay.id = 'keyDialogOverlay'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; `; document.body.appendChild(overlay); // 绑定事件 document.getElementById('cancelKeyButton').addEventListener('click', () => { dialog.remove(); overlay.remove(); }); document.getElementById('submitKeyButton').addEventListener('click', verifyKey); document.getElementById('keyInput').addEventListener('keypress', (e) => { if (e.key === 'Enter') { verifyKey(); } }); // 聚焦到输入框 setTimeout(() => { document.getElementById('keyInput').focus(); }, 100); } function verifyKey() { const keyInput = document.getElementById('keyInput'); const errorMsg = document.getElementById('keyError'); sha256(keyInput.value).then(inputHash => { if (inputHash === hashedKey) { keyVerified = true; lastVerificationTime = Date.now(); GM_setValue('lastVerificationTime', lastVerificationTime); document.getElementById('keyVerificationDialog').remove(); document.getElementById('keyDialogOverlay').remove(); init(); addControlButtons(); updateStatus('密钥验证成功!', true); } else { errorMsg.style.display = 'block'; keyInput.value = ''; keyInput.focus(); } }).catch(error => { console.error('哈希计算错误:', error); errorMsg.textContent = '验证过程中出错,请重试'; errorMsg.style.display = 'block'; }); } function createFloatingWindow() { const floatingWindow = document.createElement('div'); floatingWindow.id = 'autoFillStatus'; floatingWindow.style.cssText = ` position: fixed; top: 135px; right: 250px; background-color: rgba(0, 0, 0, 0.8); color: white; padding: 12px; border-radius: 5px; z-index: 9999; font-size: 13px; min-width: 220px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); opacity: 0.3; transition: opacity 0.3s; `; document.body.appendChild(floatingWindow); floatingWindow.onmouseenter = () => { floatingWindow.style.opacity = '1'; }; floatingWindow.onmouseleave = () => { floatingWindow.style.opacity = '0.3'; }; return floatingWindow; } function updateStatus(message, success = true) { const statusDiv = document.getElementById('autoFillStatus') || createFloatingWindow(); statusDiv.innerHTML = ` <div style="margin-bottom: 5px; font-weight: bold;">自动填写状态:</div> <div style="color: ${success ? '#4CAF50' : '#FF5252'}">${message}</div> <div style="font-size: 11px; margin-top: 5px; color: #ccc;"> <div>姓名: ${myInfo.name || '未设置'}</div> <div>班级: ${myInfo.gradeClass || '未设置'}</div> <div>联系: ${myInfo.contact || '未设置'}</div> <div>编号: ${myInfo.volunteerId || '未设置'}</div> </div> <div style="font-size: 10px; margin-top: 3px; color: #999;">延迟: ${delaySettings.fillDelay}s/${delaySettings.submitDelay}s/${delaySettings.confirmDelay}s</div> `; } function findInputsByText() { const allInputs = Array.from(document.querySelectorAll('.form-simple-main textarea')); const result = { nameInput: null, gradeClassInput: null, contactInput: null, volunteerIdInput: null }; // 为每个输入框找到最相关的标题文本 const inputTextPairs = allInputs.map(textarea => { let bestTitle = ''; let confidence = 0; // 方法1: 查找最近的标题元素 let currentElement = textarea.parentElement; let searchDepth = 0; while (currentElement && searchDepth < 3) { let prevSibling = currentElement.previousElementSibling; while (prevSibling) { const text = prevSibling.textContent.trim(); if (text.length > 0 && text.length < 50 && !text.includes('例如') && !text.includes('示例') && !text.includes('格式') && !text.includes('请输入')) { let currentConfidence = 100 - text.length; if (text.includes(':') || text.includes(':') || text.match(/^\d+[.)]/)) { currentConfidence += 20; } if (currentConfidence > confidence) { bestTitle = text.toLowerCase(); confidence = currentConfidence; } } prevSibling = prevSibling.previousElementSibling; } currentElement = currentElement.parentElement; searchDepth++; } if (confidence < 50) { const labels = document.querySelectorAll('label'); labels.forEach(label => { if (label.textContent.trim().length < 20) { const labelText = label.textContent.trim().toLowerCase(); const labelConfidence = 60; // label的置信度设为60 if (labelConfidence > confidence) { bestTitle = labelText; confidence = labelConfidence; } } }); } return { textarea: textarea, title: bestTitle, confidence: confidence, index: allInputs.indexOf(textarea) }; }); console.log('输入框标题匹配结果:', inputTextPairs.map(pair => ({ index: pair.index, title: pair.title, confidence: pair.confidence }))); const matchRules = [ { field: 'nameInput', keywords: ['姓名', 'name', '名字'], exactMatches: ['01', '1.', '1)', '(1)'] }, { field: 'gradeClassInput', keywords: ['年级', '班级', 'grade', 'class', '专业'], exactMatches: ['02', '2.', '2)', '(2)'] }, { field: 'contactInput', keywords: ['联系', '电话', '手机', 'qq', 'contact', 'phone', '微信'], exactMatches: ['03', '3.', '3)', '(3)'] }, { field: 'volunteerIdInput', keywords: ['志愿者', '编号', 'volunteer', 'id', '学号'], exactMatches: ['04', '4.', '4)', '(4)'] } ]; const sortedPairs = [...inputTextPairs].sort((a, b) => b.confidence - a.confidence); const assignedFields = new Set(); const assignedTextareas = new Set(); sortedPairs.forEach(pair => { if (assignedTextareas.has(pair.textarea)) return; for (const rule of matchRules) { if (assignedFields.has(rule.field)) continue; const hasExactMatch = rule.exactMatches.some(exact => pair.title.includes(exact.toLowerCase()) ); const hasKeywordMatch = rule.keywords.some(keyword => pair.title.includes(keyword) ); if (hasExactMatch || hasKeywordMatch) { result[rule.field] = pair.textarea; assignedFields.add(rule.field); assignedTextareas.add(pair.textarea); console.log(`匹配成功: ${rule.field} <- "${pair.title}" (置信度: ${pair.confidence})`); break; } } }); if (assignedFields.size < 4) { console.log('精确匹配未完成,按顺序分配剩余字段...'); const unassignedInputs = allInputs.filter(input => !assignedTextareas.has(input)); const unassignedFields = ['nameInput', 'gradeClassInput', 'contactInput', 'volunteerIdInput'] .filter(field => !assignedFields.has(field)); unassignedFields.forEach((field, index) => { if (index < unassignedInputs.length) { result[field] = unassignedInputs[index]; console.log(`顺序分配: ${field} <- 第${allInputs.indexOf(unassignedInputs[index]) + 1}个输入框`); } }); } console.log('最终字段分配结果:', { 姓名: result.nameInput ? `第${allInputs.indexOf(result.nameInput) + 1}个框` : '未找到', 班级: result.gradeClassInput ? `第${allInputs.indexOf(result.gradeClassInput) + 1}个框` : '未找到', 联系方式: result.contactInput ? `第${allInputs.indexOf(result.contactInput) + 1}个框` : '未找到', 志愿者编号: result.volunteerIdInput ? `第${allInputs.indexOf(result.volunteerIdInput) + 1}个框` : '未找到' }); return result; } function simulateUserInput(element, value) { element.focus(); element.value = ''; element.dispatchEvent(new Event('input', { bubbles: true })); for (let i = 0; i < value.length; i++) { element.value = value.substring(0, i + 1); element.dispatchEvent(new InputEvent('input', { bubbles: true, cancelable: true, inputType: 'insertText', data: value[i] })); } element.dispatchEvent(new Event('change', { bubbles: true })); element.blur(); element.dispatchEvent(new Event('focusout', { bubbles: true })); element.dispatchEvent(new Event('keyup', { bubbles: true })); element.dispatchEvent(new Event('keydown', { bubbles: true })); } function autoSubmit() { updateStatus('准备提交表单...', true); const submitButton = document.querySelector('button[type="button"]'); if (submitButton) { submitButton.click(); setTimeout(() => { const confirmButton = document.querySelector('.dui-modal-footer-ok'); if (confirmButton) { confirmButton.click(); updateStatus('表单已自动提交!'); } else { updateStatus('未找到确认按钮', false); } }, delaySettings.confirmDelay * 1000); } else { updateStatus('未找到提交按钮', false); } } function fillForm() { if (hasFilledForm) { return; } const inputs = findInputsByText(); let availableFields = 0; let filledCount = 0; // 计算可用字段数量 if (inputs.nameInput) availableFields++; if (inputs.gradeClassInput) availableFields++; if (inputs.contactInput) availableFields++; if (inputs.volunteerIdInput) availableFields++; if (availableFields === 0) { updateStatus('未找到任何输入框', false); return; } function checkAndSubmit() { if (filledCount === availableFields) { updateStatus('所有可用字段填写完成!准备提交...'); hasFilledForm = true; if (autoSubmitEnabled) { setTimeout(autoSubmit, delaySettings.submitDelay * 1000); } } } let currentDelay = 0; // 填写姓名 if (inputs.nameInput) { setTimeout(() => { updateStatus('正在填写姓名...', true); simulateUserInput(inputs.nameInput, myInfo.name); filledCount++; checkAndSubmit(); }, currentDelay); currentDelay += delaySettings.fillDelay * 1000; } // 填写年级班级 if (inputs.gradeClassInput) { setTimeout(() => { updateStatus('正在填写年级班级...', true); simulateUserInput(inputs.gradeClassInput, myInfo.gradeClass); filledCount++; checkAndSubmit(); }, currentDelay); currentDelay += delaySettings.fillDelay * 1000; } // 填写联系方式 if (inputs.contactInput) { setTimeout(() => { updateStatus('正在填写联系方式...', true); simulateUserInput(inputs.contactInput, myInfo.contact); filledCount++; checkAndSubmit(); }, currentDelay); currentDelay += delaySettings.fillDelay * 1000; } // 填写志愿者编号 if (inputs.volunteerIdInput) { setTimeout(() => { updateStatus('正在填写志愿者编号...', true); simulateUserInput(inputs.volunteerIdInput, myInfo.volunteerId); filledCount++; checkAndSubmit(); }, currentDelay); } if (availableFields === 0) { updateStatus('未找到任何匹配的输入框', false); } } function addControlButtons() { const buttonContainer = document.createElement('div'); buttonContainer.id = 'controlButtonsContainer'; buttonContainer.style.cssText = ` position: fixed; top: 200px; right: 300px; display: flex; flex-direction: column; gap: 8px; z-index: 9999; `; const fillButton = document.createElement('button'); fillButton.innerHTML = `填写模式: ${autoFillEnabled ? '自动' : '手动'}`; fillButton.style.cssText = ` padding: 6px 12px; background-color: ${autoFillEnabled ? '#FFA500' : '#2196F3'}; color: white; border: none; border-radius: 3px; cursor: pointer; opacity: 0.3; transition: opacity 0.3s; font-size: 12px; `; const submitToggle = document.createElement('button'); submitToggle.innerHTML = `自动提交: ${autoSubmitEnabled ? '开启' : '关闭'}`; submitToggle.style.cssText = ` padding: 6px 12px; background-color: ${autoSubmitEnabled ? '#4CAF50' : '#FF5252'}; color: white; border: none; border-radius: 3px; cursor: pointer; opacity: 0.3; transition: opacity 0.3s; font-size: 12px; `; const submitNowButton = document.createElement('button'); submitNowButton.innerHTML = '立即提交'; submitNowButton.style.cssText = ` padding: 6px 12px; background-color: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer; opacity: 0.3; transition: opacity 0.3s; font-size: 12px; `; const fillNowButton = document.createElement('button'); fillNowButton.innerHTML = '立即填写'; fillNowButton.style.cssText = ` padding: 6px 12px; background-color: #FF9800; color: white; border: none; border-radius: 3px; cursor: pointer; opacity: 0.3; transition: opacity 0.3s; font-size: 12px; `; const editInfoButton = document.createElement('button'); editInfoButton.innerHTML = '修改信息'; editInfoButton.style.cssText = ` padding: 6px 12px; background-color: #9C27B0; color: white; border: none; border-radius: 3px; cursor: pointer; opacity: 0.3; transition: opacity 0.3s; font-size: 12px; `; const delayButton = document.createElement('button'); delayButton.innerHTML = '延迟设置'; delayButton.style.cssText = ` padding: 6px 12px; background-color: #607D8B; color: white; border: none; border-radius: 3px; cursor: pointer; opacity: 0.3; transition: opacity 0.3s; font-size: 12px; `; const resetKeyButton = document.createElement('button'); resetKeyButton.innerHTML = '重置密钥'; resetKeyButton.style.cssText = ` padding: 6px 12px; background-color: #795548; color: white; border: none; border-radius: 3px; cursor: pointer; opacity: 0.3; transition: opacity 0.3s; font-size: 12px; `; [fillButton, submitToggle, submitNowButton, fillNowButton, editInfoButton, delayButton, resetKeyButton].forEach(button => { button.onmouseenter = () => { button.style.opacity = '1'; }; button.onmouseleave = () => { button.style.opacity = '0.3'; }; }); fillButton.onclick = () => { autoFillEnabled = !autoFillEnabled; GM_setValue('autoFillEnabled', autoFillEnabled); fillButton.innerHTML = `填写模式: ${autoFillEnabled ? '自动' : '手动'}`; fillButton.style.backgroundColor = autoFillEnabled ? '#FFA500' : '#2196F3'; updateStatus(`当前模式: ${autoFillEnabled ? '自动填写' : '手动填写'}`); if (autoFillEnabled && !hasFilledForm) { fillForm(); } }; submitToggle.onclick = () => { autoSubmitEnabled = !autoSubmitEnabled; GM_setValue('autoSubmitEnabled', autoSubmitEnabled); submitToggle.innerHTML = `自动提交: ${autoSubmitEnabled ? '开启' : '关闭'}`; submitToggle.style.backgroundColor = autoSubmitEnabled ? '#4CAF50' : '#FF5252'; if (autoSubmitEnabled && hasFilledForm) { autoSubmit(); } }; submitNowButton.onclick = () => { autoSubmit(); }; fillNowButton.onclick = () => { hasFilledForm = false; // 重置填写状态 fillForm(); }; editInfoButton.onclick = () => { createInfoDialog(false); }; delayButton.onclick = () => { createDelayDialog(); }; resetKeyButton.onclick = () => { keyVerified = false; GM_setValue('lastVerificationTime', 0); document.getElementById('controlButtonsContainer').remove(); createKeyDialog(); updateStatus('已重置密钥验证状态,请重新验证', false); }; buttonContainer.appendChild(fillButton); buttonContainer.appendChild(submitToggle); buttonContainer.appendChild(submitNowButton); buttonContainer.appendChild(fillNowButton); buttonContainer.appendChild(editInfoButton); buttonContainer.appendChild(delayButton); buttonContainer.appendChild(resetKeyButton); document.body.appendChild(buttonContainer); } function init() { if (!document.getElementById('autoFillStatus')) { createFloatingWindow(); } if (document.readyState === 'complete') { updateStatus('正在查找表单...'); if (autoFillEnabled) { fillForm(); } else { updateStatus('当前为手动填写模式'); } } else { updateStatus('等待页面加载...', false); setTimeout(init, 100); } } // 主入口 setTimeout(() => { // 首先检查是否已设置个人信息 if (!checkUserInfo()) { createFloatingWindow(); updateStatus('首次使用,请设置个人信息', false); createInfoDialog(true); return; } if (checkKeyValidity()) { init(); addControlButtons(); updateStatus('密钥已验证,脚本已启动', true); } else { createFloatingWindow(); updateStatus('请输入密钥验证', false); createKeyDialog(); } }, 200); // 额外检查 setTimeout(() => { if (keyVerified && !hasFilledForm && document.getElementById('autoFillStatus')) { init(); } }, 500); // 页面变化监听 - 处理动态加载的表单 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length > 0) { // 检查是否有新的表单元素添加 const hasFormElements = Array.from(mutation.addedNodes).some(node => { return node.nodeType === Node.ELEMENT_NODE && (node.querySelector && node.querySelector('.form-simple-main textarea')); }); if (hasFormElements && keyVerified && !hasFilledForm && autoFillEnabled) { setTimeout(() => { fillForm(); }, 1000); } } }); }); // 开始观察 observer.observe(document.body, { childList: true, subtree: true }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址