// ==UserScript==
// @name 特种考试自动答题脚本-中安云教育
// @namespace http://tampermonkey.net/
// @version 4.2.0
// @description 特种考试自动答题脚本-中安云教育
// @author You
// @match https://txsyaqpx.zhongancloud.com/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @grant GM_info
// @grant unsafeWindow
// @require https://lib.baomitu.com/jquery/3.6.0/jquery.min.js
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// 全局配置
const CONFIG = {
delay: 2000,
stop: true,
minDelay: 1000, // 最小延时1秒
autoSubmit: false, // 自动提交试卷
// 智谱AI应用配置(使用最新API)
ZHIPU_CONFIG: {
api_key: '51ae1d1540dd4d2d9418c32d3cefd868.3nX8rj0r87zTFSdl',
application_id: '1975919497449705472', // 您的智能体ID作为应用ID
knowledge_base_id: '1975919768523378688',
base_url: 'https://open.bigmodel.cn/api/llm-application/open'
}
};
let logContainer;
let stats = {
total: 0,
processed: 0,
success: 0,
failed: 0,
knowledgeHits: 0,
aiBackup: 0
};
// 日志函数
function log(message) {
const time = new Date().toLocaleTimeString();
const logMessage = `[${time}] ${message}`;
console.log(logMessage);
if (logContainer) {
// 创建新的日志条目
const logEntry = document.createElement('div');
logEntry.style.cssText = 'margin-bottom: 5px; word-wrap: break-word; white-space: pre-wrap; line-height: 1.7; padding: 3px 0; font-size: 12px; min-height: 20px;';
logEntry.textContent = logMessage;
logContainer.appendChild(logEntry);
// 限制日志条目数量,避免过多影响性能
const maxLogs = 200;
while (logContainer.children.length > maxLogs) {
logContainer.removeChild(logContainer.firstChild);
}
// 强制滚动到底部,确保新内容可见
requestAnimationFrame(() => {
logContainer.scrollTop = logContainer.scrollHeight;
// 双重确保滚动到底部
setTimeout(() => {
logContainer.scrollTop = logContainer.scrollHeight;
}, 50);
});
}
}
// 调用智谱应用API(使用最新接口)
async function callKnowledgeBaseAPI(question, options) {
const query = `请回答这道低压电工题目,严格按照格式返回:
题目:${question}
选项:
${options.map((opt, i) => `${String.fromCharCode(65 + i)}. ${opt}`).join('\n')}
要求:
1. 基于低压电工专业知识选择正确答案
2. 严格按照格式:选项字母,选项原文
3. 选项原文必须与上面选项完全一致
4. 不要添加解释或额外内容
格式示例:A,正确 或 B,错误 或 C,竖放
答案:`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'POST',
url: `${CONFIG.ZHIPU_CONFIG.base_url}/v3/application/invoke`,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CONFIG.ZHIPU_CONFIG.api_key}`
},
data: JSON.stringify({
app_id: CONFIG.ZHIPU_CONFIG.application_id,
stream: false,
messages: [
{
role: "user",
content: [
{
type: "input",
value: query
}
]
}
]
}),
timeout: 8000,
onload: function(response) {
try {
// 简化日志输出
if (response.status !== 200) {
reject(new Error(`知识库API错误: ${response.status}`));
return;
}
const result = JSON.parse(response.responseText);
if (result.choices && result.choices[0] && result.choices[0].messages) {
const messages = result.choices[0].messages;
const content = messages.content;
if (content && content.type === "text" && content.msg) {
const answer = content.msg.trim();
log(`🧠 AI回答: ${answer}`);
stats.knowledgeHits++;
resolve(answer);
} else {
log(`❌ 智能体响应内容格式错误`);
reject(new Error('智能体响应内容格式错误'));
}
} else {
log(`❌ 智能体API错误: ${result.message || '未知错误'}`);
reject(new Error(result.message || '智能体API调用失败'));
}
} catch (e) {
log(`❌ 知识库响应解析失败: ${e.message}`);
reject(new Error('知识库响应解析失败'));
}
},
onerror: function(error) {
log(`❌ 知识库网络错误: ${JSON.stringify(error)}`);
reject(new Error('知识库网络请求失败'));
}
});
});
}
// 备用AI调用(修复版)
async function callBackupAI(question, options) {
const prompt = `请回答这道${options.length === 2 ? '判断' : '选择'}题,严格按照格式返回:
题目:${question}
选项:
${options.map((opt, i) => `${String.fromCharCode(65 + i)}. ${opt}`).join('\n')}
要求:
1. 选择正确答案
2. 格式:选项字母,选项原文
3. 选项原文必须与上面选项完全一致
4. 不要解释
答案:`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'POST',
url: `${CONFIG.ZHIPU_CONFIG.base_url}/chat/completions`,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CONFIG.ZHIPU_CONFIG.api_key}`
},
data: JSON.stringify({
model: 'glm-4-flash',
messages: [
{
role: "system",
content: "你是专业的低压电工,只回答选项字母,不要解释。"
},
{
role: "user",
content: prompt
}
],
temperature: 0.1,
max_tokens: 20
}),
timeout: 6000,
onload: function(response) {
try {
const result = JSON.parse(response.responseText);
if (result.choices && result.choices[0]) {
const answer = result.choices[0].message.content.trim();
log(`🤖 备用AI回答: "${answer}"`);
stats.aiBackup++;
resolve(answer);
} else if (result.error) {
log(`❌ 备用AI错误: ${result.error.message}`);
reject(new Error('备用AI响应错误'));
} else {
reject(new Error('备用AI响应格式错误'));
}
} catch (e) {
log(`❌ 备用AI解析失败: ${e.message}`);
reject(new Error('备用AI解析失败'));
}
},
onerror: () => reject(new Error('备用AI网络错误'))
});
});
}
// 智能获取答案
async function getSmartAnswer(question, options) {
// 优先使用知识库
try {
log('📚 正在调用知识库...');
const knowledgeAnswer = await callKnowledgeBaseAPI(question, options);
return knowledgeAnswer;
} catch (error) {
log(`⚠️ 知识库调用失败: ${error.message}`);
// 备用AI
try {
log('🤖 使用备用AI...');
const aiAnswer = await callBackupAI(question, options);
return aiAnswer;
} catch (aiError) {
log(`❌ 备用AI也失败: ${aiError.message}`);
throw new Error('所有答案获取方式都失败');
}
}
}
// 更新时间预估
function updateTimeEstimate() {
const delayInput = document.getElementById('delayInput');
const timeEstimate = document.getElementById('timeEstimate');
if (delayInput && timeEstimate) {
const delaySeconds = parseInt(delayInput.value) || 3;
const containers = document.querySelectorAll('.ques-type-item');
let questionCount = containers.length;
// 如果还没检测到题目,使用默认值并标注
let isEstimated = false;
if (questionCount === 0) {
questionCount = 100;
isEstimated = true;
}
// 计算总时间(延时 + 处理时间)
const processingTimePerQuestion = 1.5; // 每题处理时间约1.5秒(优化后)
const totalTimePerQuestion = delaySeconds + processingTimePerQuestion;
const totalSeconds = questionCount * totalTimePerQuestion;
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
let timeText = '';
if (minutes > 0) {
timeText = `${minutes}分${seconds}秒`;
} else {
timeText = `${totalSeconds}秒`;
}
const estimateText = isEstimated ?
`预计完成时间: ${timeText} (预估${questionCount}题)` :
`预计完成时间: ${timeText} (${questionCount}题)`;
timeEstimate.textContent = estimateText;
timeEstimate.style.color = isEstimated ? '#a0aec0' : '#718096';
}
}
// 将函数设为全局,以便HTML中调用
window.updateTimeEstimate = updateTimeEstimate;
window.showDonateModal = showDonateModal;
// 自动提交试卷
async function autoSubmitExam() {
try {
log('🎯 正在自动提交试卷...');
// 查找提交按钮 - 根据页面结构优化
const submitSelectors = [
'button[type="submit"]',
'.submit-btn',
'.btn-submit',
'input[type="submit"]',
'.exam-submit',
'#submitBtn',
'.btn-primary',
'.submit-button',
// 根据截图添加可能的选择器
'button[style*="background-color: rgb(24, 144, 255)"]',
'button[style*="background: rgb(24, 144, 255)"]',
'.ant-btn-primary',
'[class*="submit"]',
'[class*="primary"]'
];
let submitBtn = null;
for (const selector of submitSelectors) {
try {
submitBtn = document.querySelector(selector);
if (submitBtn) {
log(`✅ 通过选择器找到提交按钮: ${selector}`);
break;
}
} catch (e) {
// 忽略无效选择器错误
continue;
}
}
// 如果没找到,尝试通过文本查找
if (!submitBtn) {
log('🔍 开始通过文本查找提交按钮...');
const buttons = document.querySelectorAll('button, input[type="button"], a, .btn, [role="button"], div[role="button"]');
for (const btn of buttons) {
const text = (btn.textContent || btn.value || btn.innerText || '').trim();
// 优先查找"提交试卷"
if (text === '提交试卷' || text === '提交答案' || text === '提交考试') {
submitBtn = btn;
log(`✅ 精确匹配找到提交按钮: "${text}"`);
break;
}
// 其他提交相关文本
if (text.includes('提交') || text.includes('完成') || text.includes('结束') ||
text.includes('交卷') || text.includes('确认') || text.includes('保存') ||
text.includes('submit') || text.includes('finish') || text.includes('complete')) {
submitBtn = btn;
log(`✅ 通过文本找到提交按钮: "${text}"`);
break;
}
}
}
// 如果还是没找到,尝试查找页面右下角的蓝色按钮(根据截图)
if (!submitBtn) {
const blueButtons = document.querySelectorAll('button, .btn, [style*="background"], [class*="primary"], [class*="blue"]');
for (const btn of blueButtons) {
const rect = btn.getBoundingClientRect();
const isRightSide = rect.right > window.innerWidth * 0.7;
const isBottomSide = rect.bottom > window.innerHeight * 0.7;
if (isRightSide && isBottomSide) {
const text = (btn.textContent || btn.value || '').trim();
log(`🔍 发现右下角按钮: "${text}"`);
if (text.length > 0) {
submitBtn = btn;
log(`✅ 选择右下角按钮作为提交按钮: "${text}"`);
break;
}
}
}
}
if (submitBtn) {
log('✅ 找到提交按钮,准备提交...');
// 等待2秒后提交
await new Promise(resolve => setTimeout(resolve, 2000));
submitBtn.click();
log('🎉 试卷已自动提交!');
return true;
} else {
log('❌ 未找到提交按钮,请手动提交');
return false;
}
} catch (error) {
log(`❌ 自动提交失败: ${error.message}`);
return false;
}
}
// 解析答案(增强版)- 返回详细信息
function parseAnswer(answer, options = []) {
const cleanAnswer = answer.trim();
log(`🔍 解析答案: "${cleanAnswer}"`);
// 1. 解析"字母,内容"格式(最优先)
const commaMatch = cleanAnswer.match(/^([A-D])[,,]\s*(.+)$/i);
if (commaMatch) {
const letter = commaMatch[1].toUpperCase();
const content = commaMatch[2].trim();
// 通过内容匹配找到正确的选项索引
let bestMatch = null;
let bestScore = 0;
for (let i = 0; i < options.length; i++) {
const option = options[i].trim();
let score = 0;
// 完全匹配(最高优先级)
if (option === content) {
score = 1.0;
}
// 选项包含AI内容
else if (option.includes(content)) {
score = 0.9;
}
// AI内容包含选项
else if (content.includes(option)) {
score = 0.8;
}
// 相似度匹配
else {
score = parseAnswer.contentSimilarity(option, content);
}
if (score > bestScore && score > 0.6) {
bestScore = score;
bestMatch = {
letter: String.fromCharCode(65 + i),
index: i,
content: option,
source: 'format_content_match',
aiLetter: letter,
aiContent: content,
matchScore: score
};
}
}
if (bestMatch) {
log(`✅ 格式解析+内容匹配: AI说"${letter},${content}" -> 实际选项${bestMatch.letter}: ${bestMatch.content} (匹配度:${(bestMatch.matchScore*100).toFixed(0)}%)`);
return bestMatch;
}
// 如果内容匹配失败,尝试使用AI提供的字母(但要验证)
const aiIndex = letter.charCodeAt(0) - 65;
if (aiIndex >= 0 && aiIndex < options.length) {
const result = {
letter: letter,
index: aiIndex,
content: options[aiIndex],
source: 'format_letter_fallback',
aiContent: content
};
log(`⚠️ 内容不匹配,使用AI字母: ${letter} -> ${result.content} (AI说的内容: ${content})`);
return result;
}
}
// 2. 直接匹配单个字母
const upperAnswer = cleanAnswer.toUpperCase();
if (/^[A-Z]$/.test(upperAnswer)) {
const index = upperAnswer.charCodeAt(0) - 65;
if (index >= 0 && index < options.length) {
const result = {
letter: upperAnswer,
index: index,
content: options[index],
source: 'direct_letter'
};
log(`✅ 直接匹配: ${upperAnswer} -> ${result.content}`);
return result;
}
}
// 3. 提取第一个字母
const letterMatch = upperAnswer.match(/[A-Z]/);
if (letterMatch) {
const letter = letterMatch[0];
const index = letter.charCodeAt(0) - 65;
if (index >= 0 && index < options.length) {
const result = {
letter: letter,
index: index,
content: options[index],
source: 'extract_letter'
};
log(`✅ 提取字母: ${letter} -> ${result.content}`);
return result;
}
}
// 4. 判断题关键词匹配
if (upperAnswer.includes('正确') || upperAnswer.includes('对') || upperAnswer.includes('TRUE')) {
// 找到包含"正确"的选项
for (let i = 0; i < options.length; i++) {
if (options[i].includes('正确') || options[i].includes('对')) {
const result = {
letter: String.fromCharCode(65 + i),
index: i,
content: options[i],
source: 'keyword_correct'
};
log(`✅ 判断题-正确: ${result.letter} -> ${result.content}`);
return result;
}
}
} else if (upperAnswer.includes('错误') || upperAnswer.includes('错') || upperAnswer.includes('FALSE')) {
// 找到包含"错误"的选项
for (let i = 0; i < options.length; i++) {
if (options[i].includes('错误') || options[i].includes('错')) {
const result = {
letter: String.fromCharCode(65 + i),
index: i,
content: options[i],
source: 'keyword_wrong'
};
log(`✅ 判断题-错误: ${result.letter} -> ${result.content}`);
return result;
}
}
}
// 5. 选项内容关键词匹配
if (options.length > 0) {
for (let i = 0; i < options.length; i++) {
const option = options[i].trim();
const optionWords = option.split(/[\s,。、]/);
for (const word of optionWords) {
if (word.length >= 2 && upperAnswer.includes(word.toUpperCase())) {
const letter = String.fromCharCode(65 + i);
const result = {
letter: letter,
index: i,
content: option,
source: 'content_match'
};
log(`✅ 内容匹配: "${word}" -> ${letter}: ${result.content}`);
return result;
}
}
}
}
log(`❌ 无法解析答案: "${cleanAnswer}"`);
return null;
}
// 内容相似度计算(简单版)
parseAnswer.contentSimilarity = function(str1, str2) {
const s1 = str1.toLowerCase().replace(/[^\w\u4e00-\u9fff]/g, '');
const s2 = str2.toLowerCase().replace(/[^\w\u4e00-\u9fff]/g, '');
if (s1 === s2) return 1;
if (s1.includes(s2) || s2.includes(s1)) return 0.8;
// 简单的字符重叠度计算
let overlap = 0;
const minLen = Math.min(s1.length, s2.length);
for (let i = 0; i < minLen; i++) {
if (s1[i] === s2[i]) overlap++;
}
return overlap / Math.max(s1.length, s2.length);
};
// 处理单个题目
async function processQuestion(container, index) {
try {
log(`\n📝 === 第 ${index + 1} 题 ===`);
// 提取题目
const questionEl = container.querySelector('.question-name .content p');
if (!questionEl) {
log(`❌ 找不到题目`);
return false;
}
const question = questionEl.textContent.trim();
log(`📖 题目: ${question.substring(0, 30)}...`);
// 提取选项
const optionGroups = container.querySelectorAll('.option-group');
const options = [];
optionGroups.forEach(group => {
const content = group.querySelector('.option-content p');
if (content) {
const text = content.textContent.trim();
if (text && !options.includes(text)) {
options.push(text);
}
}
});
if (options.length === 0) {
log(`❌ 找不到选项`);
return false;
}
log(`📋 选项(${options.length}个): ${options.map(opt => opt.substring(0, 8)).join(' | ')}`);
// 获取智能答案
const answer = await getSmartAnswer(question, options);
// 解析并点击
const parseResult = parseAnswer(answer, options);
if (parseResult && parseResult.index >= 0 && parseResult.index < optionGroups.length) {
const targetGroup = optionGroups[parseResult.index];
const radioInput = targetGroup.querySelector('input[type="radio"]');
if (radioInput) {
radioInput.checked = true;
radioInput.dispatchEvent(new Event('change', { bubbles: true }));
targetGroup.click();
log(`✅ 已选择: ${parseResult.letter} - ${parseResult.content}`);
stats.success++;
return true;
}
}
log(`❌ 无法选择答案: 解析失败或选项不存在`);
stats.failed++;
return false;
} catch (error) {
log(`❌ 处理异常: ${error.message}`);
stats.failed++;
return false;
} finally {
stats.processed++;
}
}
// 显示打赏弹窗
function showDonateModal() {
// 创建遮罩层
const overlay = document.createElement('div');
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 20000;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(5px);
`;
// 创建弹窗
const modal = document.createElement('div');
modal.style.cssText = `
background: #f0f2f5;
border-radius: 20px;
padding: 30px;
max-width: 400px;
text-align: center;
box-shadow:
20px 20px 40px rgba(0,0,0,0.2),
-20px -20px 40px rgba(255,255,255,0.9);
position: relative;
`;
modal.innerHTML = `
❤️
感谢支持
如果脚本对您有帮助,请考虑打赏支持作者
`;
overlay.className = 'donate-overlay';
overlay.appendChild(modal);
document.body.appendChild(overlay);
// 绑定按钮事件
setTimeout(() => {
const closeBtn = document.getElementById('closeModalBtn');
const contactBtn = document.getElementById('contactBtn');
if (closeBtn) {
closeBtn.onclick = () => overlay.remove();
}
if (contactBtn) {
contactBtn.onclick = () => copyWechatId(contactBtn);
}
}, 100);
// 点击遮罩关闭
overlay.onclick = (e) => {
if (e.target === overlay) {
overlay.remove();
}
};
log('❤️ 显示打赏弹窗');
}
// 复制微信号
function copyWechatId(button) {
const wechatId = 'C919irt';
try {
// 尝试使用现代API
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(wechatId).then(() => {
showCopySuccess(button, wechatId);
}).catch(() => {
fallbackCopy(wechatId, button);
});
} else {
fallbackCopy(wechatId, button);
}
} catch (error) {
fallbackCopy(wechatId, button);
}
}
// 备用复制方法
function fallbackCopy(text, button) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
showCopySuccess(button, text);
} catch (err) {
showCopyFailed(button, text);
}
document.body.removeChild(textArea);
}
// 显示复制成功
function showCopySuccess(button, wechatId) {
const originalText = button.textContent;
button.textContent = '✅ 已复制微信号';
button.style.color = '#38a169';
setTimeout(() => {
button.textContent = originalText;
button.style.color = '#38a169';
}, 2000);
log(`✅ 微信号已复制: ${wechatId}`);
// 显示提示
const tip = document.createElement('div');
tip.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #38a169;
color: white;
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
z-index: 25000;
box-shadow: 0 4px 12px rgba(56, 161, 105, 0.3);
`;
tip.textContent = `微信号 ${wechatId} 已复制到剪贴板`;
document.body.appendChild(tip);
setTimeout(() => {
tip.remove();
}, 3000);
}
// 显示复制失败
function showCopyFailed(button, wechatId) {
const originalText = button.textContent;
button.textContent = `微信号: ${wechatId}`;
button.style.color = '#ed8936';
setTimeout(() => {
button.textContent = originalText;
button.style.color = '#38a169';
}, 3000);
log(`❌ 复制失败,微信号: ${wechatId}`);
}
// 设置全局函数
window.copyWechatId = copyWechatId;
// 开始答题
function startAnswering() {
if (!CONFIG.stop) return;
CONFIG.stop = false;
stats = { total: 0, processed: 0, success: 0, failed: 0, knowledgeHits: 0, aiBackup: 0 };
// 获取延时和自动提交设置
const delaySeconds = parseInt(document.getElementById('delayInput')?.value || 3);
const delay = delaySeconds * 1000; // 转换为毫秒
CONFIG.autoSubmit = document.getElementById('autoSubmitCheck')?.checked || false;
log('🚀 开始知识库增强答题');
log(`📚 使用知识库: ${CONFIG.ZHIPU_CONFIG.knowledge_base_id}`);
log(`⏱️ 答题延时: ${delaySeconds}秒/题`);
log(`📋 自动提交: ${CONFIG.autoSubmit ? '已启用' : '已禁用'}`);
const containers = document.querySelectorAll('.ques-type-item');
stats.total = containers.length;
// 计算预计完成时间(包含处理时间)
const processingTimePerQuestion = 1.5; // 每题处理时间约1.5秒(优化后)
const totalTimePerQuestion = delaySeconds + processingTimePerQuestion;
const totalSeconds = stats.total * totalTimePerQuestion;
const minutes = Math.floor(totalSeconds / 60);
const remainingSeconds = Math.round(totalSeconds % 60);
const timeText = minutes > 0 ? `${minutes}分${remainingSeconds}秒` : `${totalSeconds}秒`;
log(`📚 找到 ${stats.total} 道题目`);
log(`⏰ 预计完成时间: ${timeText} (含处理时间)`);
log(`📊 计算方式: ${stats.total}题 × (${delaySeconds}秒延时 + 2秒处理) = ${totalSeconds}秒`);
(async () => {
const startTime = Date.now();
for (let i = 0; i < containers.length && !CONFIG.stop; i++) {
await processQuestion(containers[i], i);
const progress = Math.round((i + 1) / containers.length * 100);
const accuracy = stats.processed > 0 ? Math.round(stats.success / stats.processed * 100) : 0;
const knowledgeRate = stats.processed > 0 ? Math.round(stats.knowledgeHits / stats.processed * 100) : 0;
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
log(`📊 进度: ${i + 1}/${containers.length} (${progress}%) | 准确率: ${accuracy}% | 已用时: ${elapsed}秒`);
if (i < containers.length - 1) {
await new Promise(resolve => setTimeout(resolve, delay));
}
}
const finalScore = Math.round(stats.success / stats.total * 100);
const knowledgeUsage = Math.round(stats.knowledgeHits / stats.processed * 100);
const totalTime = ((Date.now() - startTime) / 1000).toFixed(1);
log(`\n🎉 知识库答题完成!`);
log(`📊 最终统计:`);
log(` • 总题目: ${stats.total}题`);
log(` • 成功: ${stats.success}题`);
log(` • 知识库使用: ${stats.knowledgeHits}次 (${knowledgeUsage}%)`);
log(` • 备用AI使用: ${stats.aiBackup}次`);
log(` • 总用时: ${totalTime}秒`);
log(`📈 预估得分: ${finalScore}分`);
log(`🎯 相比82分: ${finalScore > 82 ? '提升' : '下降'}${Math.abs(finalScore - 82)}分`);
// 自动提交试卷
if (CONFIG.autoSubmit) {
log(`\n🎯 准备自动提交试卷...`);
await autoSubmitExam();
}
CONFIG.stop = true;
})();
}
// 停止答题
function stopAnswering() {
CONFIG.stop = true;
log('⏹️ 停止答题');
}
// 创建控制面板
function createPanel() {
const panel = document.createElement('div');
panel.id = 'knowledgePanel';
panel.style.cssText = `
position: fixed;
top: 30px;
right: 20px;
width: 360px;
height: auto;
min-width: 300px;
min-height: 450px;
max-width: 600px;
max-height: 95vh;
background: #f0f2f5;
border: none;
border-radius: 20px;
box-shadow:
20px 20px 40px rgba(0,0,0,0.1),
-20px -20px 40px rgba(255,255,255,0.8),
inset 0 0 0 1px rgba(255,255,255,0.3);
z-index: 10000;
font-family: 'Microsoft YaHei', Arial, sans-serif;
transition: none;
backdrop-filter: blur(10px);
overflow-y: auto;
overflow-x: hidden;
`;
panel.innerHTML = `
🔮 智能知识库引擎
应用ID: ****${CONFIG.ZHIPU_CONFIG.application_id.substr(-4)} | 知识库: ****${CONFIG.ZHIPU_CONFIG.knowledge_base_id.substr(-4)}
📚 答题助手已就绪...
🧠 已配置真实知识库API调用
🎯 目标:利用专业知识库达到95分+
💡 知识库优先,AI备用
🎯 智能答题系统
知识库优先 + AI备用 + 智能匹配
`;
document.body.appendChild(panel);
logContainer = document.getElementById('logArea');
// 创建最小化悬浮窗
createFloatingPet();
// 绑定事件
setTimeout(() => {
const donateBtn = document.getElementById('donateBtn');
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const minimizeBtn = document.getElementById('minimizeBtn');
const closeBtn = document.getElementById('closeBtn');
const autoSubmitCheck = document.getElementById('autoSubmitCheck');
const checkboxDisplay = document.getElementById('checkboxDisplay');
if (donateBtn) donateBtn.onclick = showDonateModal;
if (startBtn) startBtn.onclick = startAnswering;
if (stopBtn) stopBtn.onclick = stopAnswering;
if (minimizeBtn) minimizeBtn.onclick = minimizePanel;
if (closeBtn) closeBtn.onclick = closePanel;
// 复选框交互
if (autoSubmitCheck && checkboxDisplay) {
const updateCheckbox = () => {
const isChecked = autoSubmitCheck.checked;
const indicator = checkboxDisplay.querySelector('div');
if (indicator) {
indicator.style.transform = isChecked ? 'scale(1)' : 'scale(0)';
}
checkboxDisplay.style.boxShadow = isChecked ?
'inset 6px 6px 12px rgba(0,0,0,0.15), inset -6px -6px 12px rgba(255,255,255,0.9)' :
'inset 4px 4px 8px rgba(0,0,0,0.1), inset -4px -4px 8px rgba(255,255,255,0.8)';
};
autoSubmitCheck.onchange = updateCheckbox;
checkboxDisplay.onclick = () => {
autoSubmitCheck.checked = !autoSubmitCheck.checked;
updateCheckbox();
};
// 初始状态
updateCheckbox();
}
// 拖拽功能
setupDragFunctionality();
// 初始化时间预估
setTimeout(() => {
updateTimeEstimate();
// 定期更新时间预估(检测到题目后更新)
setInterval(updateTimeEstimate, 2000);
}, 500);
log('✅ 面板已就绪,支持拖拽和最小化');
}, 100);
// 实时更新统计
setInterval(() => {
const statsArea = document.getElementById('statsArea');
const pet = document.getElementById('floatingPet');
if (statsArea && stats.total > 0) {
const progress = Math.round((stats.processed / stats.total) * 100);
const accuracy = stats.processed > 0 ? Math.round((stats.success / stats.processed) * 100) : 0;
const knowledgeRate = stats.processed > 0 ? Math.round((stats.knowledgeHits / stats.processed) * 100) : 0;
const aiRate = stats.processed > 0 ? Math.round((stats.aiBackup / stats.processed) * 100) : 0;
statsArea.innerHTML = `
进度
${stats.processed}/${stats.total}
📚 知识库: ${stats.knowledgeHits}次 | 🤖 备用AI: ${stats.aiBackup}次
`;
// 同时更新悬浮宠物状态
if (pet && pet.style.display === 'flex') {
pet.className = ''; // 清除之前的状态类
if (CONFIG.stop === false && stats.processed > 0) {
// 答题进行中
pet.className = 'pet-working';
pet.innerHTML = `
`;
pet.title = `🚀 答题进行中: ${stats.processed}/${stats.total} (准确率${accuracy}%) - 点击展开面板`;
} else if (stats.processed > 0) {
// 答题完成
if (accuracy >= 90) {
pet.className = 'pet-success';
pet.innerHTML = `
`;
} else {
pet.className = 'pet-warning';
pet.innerHTML = `
`;
}
pet.title = `✅ 答题完成: ${accuracy}分 (${stats.success}/${stats.total}) - 点击展开面板`;
} else {
// 待机状态
pet.innerHTML = `
`;
pet.title = '🤖 知识库答题助手 - 点击展开面板';
}
}
}
}, 1000);
}
// 创建悬浮小宠物
function createFloatingPet() {
const pet = document.createElement('div');
pet.id = 'floatingPet';
pet.style.cssText = `
position: fixed;
top: 50px;
right: 20px;
width: 75px;
height: 75px;
background: #f0f2f5;
border-radius: 50%;
box-shadow:
12px 12px 24px rgba(0,0,0,0.15),
-12px -12px 24px rgba(255,255,255,0.9);
z-index: 10001;
cursor: pointer;
display: none;
align-items: center;
justify-content: center;
font-size: 28px;
color: #4a5568;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
user-select: none;
animation: petFloat 4s ease-in-out infinite;
border: none;
`;
pet.innerHTML = `
`;
pet.title = '知识库答题助手 - 点击展开';
pet.onclick = restorePanel;
// 添加悬浮动画和样式
const style = document.createElement('style');
style.textContent = `
/* 强制显示滚动条样式 */
#logArea {
scrollbar-width: thin !important;
scrollbar-color: #a0aec0 #f0f2f5 !important;
overflow-y: scroll !important;
overflow-x: hidden !important;
}
#logArea::-webkit-scrollbar {
width: 12px !important;
height: 12px !important;
display: block !important;
}
#logArea::-webkit-scrollbar-track {
background: #e2e8f0 !important;
border-radius: 6px !important;
box-shadow: inset 3px 3px 6px rgba(0,0,0,0.1), inset -3px -3px 6px rgba(255,255,255,0.8) !important;
border: 1px solid #cbd5e0 !important;
}
#logArea::-webkit-scrollbar-thumb {
background: linear-gradient(135deg, #a0aec0, #718096) !important;
border-radius: 6px !important;
box-shadow: 2px 2px 4px rgba(0,0,0,0.2), -2px -2px 4px rgba(255,255,255,0.9) !important;
border: 2px solid #f0f2f5 !important;
min-height: 30px !important;
}
#logArea::-webkit-scrollbar-thumb:hover {
background: linear-gradient(135deg, #718096, #4a5568) !important;
box-shadow: inset 2px 2px 4px rgba(0,0,0,0.15), inset -2px -2px 4px rgba(255,255,255,0.9) !important;
}
#logArea::-webkit-scrollbar-thumb:active {
background: linear-gradient(135deg, #4a5568, #2d3748) !important;
box-shadow: inset 3px 3px 6px rgba(0,0,0,0.2), inset -3px -3px 6px rgba(255,255,255,0.8) !important;
}
#logArea::-webkit-scrollbar-corner {
background: #f0f2f5 !important;
}
@keyframes petFloat {
0%, 100% {
transform: translateY(0px) rotate(0deg);
box-shadow:
12px 12px 24px rgba(0,0,0,0.15),
-12px -12px 24px rgba(255,255,255,0.9);
}
25% {
transform: translateY(-6px) rotate(1deg);
box-shadow:
15px 15px 30px rgba(0,0,0,0.2),
-15px -15px 30px rgba(255,255,255,0.95);
}
50% {
transform: translateY(-10px) rotate(0deg);
box-shadow:
18px 18px 36px rgba(0,0,0,0.25),
-18px -18px 36px rgba(255,255,255,1);
}
75% {
transform: translateY(-6px) rotate(-1deg);
box-shadow:
15px 15px 30px rgba(0,0,0,0.2),
-15px -15px 30px rgba(255,255,255,0.95);
}
}
@keyframes petPulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
#floatingPet:hover {
transform: scale(1.1) translateY(-3px) !important;
box-shadow:
inset 6px 6px 12px rgba(0,0,0,0.1),
inset -6px -6px 12px rgba(255,255,255,0.8) !important;
animation: petPulse 1s ease-in-out infinite !important;
}
#floatingPet:active {
transform: scale(0.95) !important;
transition: all 0.1s ease !important;
box-shadow:
inset 8px 8px 16px rgba(0,0,0,0.15),
inset -8px -8px 16px rgba(255,255,255,0.9) !important;
}
/* 状态指示器样式 */
.pet-working {
background: #e6fffa !important;
color: #38a169 !important;
animation: petFloat 2s ease-in-out infinite, petPulse 1.5s ease-in-out infinite !important;
box-shadow:
12px 12px 24px rgba(56, 161, 105, 0.2),
-12px -12px 24px rgba(255,255,255,0.9) !important;
}
.pet-success {
background: #ebf8ff !important;
color: #3182ce !important;
box-shadow:
12px 12px 24px rgba(49, 130, 206, 0.2),
-12px -12px 24px rgba(255,255,255,0.9) !important;
}
.pet-warning {
background: #fffaf0 !important;
color: #ed8936 !important;
box-shadow:
12px 12px 24px rgba(237, 137, 54, 0.2),
-12px -12px 24px rgba(255,255,255,0.9) !important;
}
`;
document.head.appendChild(style);
document.body.appendChild(pet);
}
// 设置拖拽和调整大小功能
function setupDragFunctionality() {
const panel = document.getElementById('knowledgePanel');
const header = document.getElementById('panelHeader');
const pet = document.getElementById('floatingPet');
let isDragging = false;
let dragOffset = { x: 0, y: 0 };
// 移除调整大小控制点(用户要求取消)
// addResizeHandles(panel);
// 面板拖拽
if (header) {
header.onmousedown = (e) => {
// 如果点击的是按钮,不触发拖拽
if (e.target.id === 'minimizeBtn' || e.target.id === 'closeBtn') {
return;
}
isDragging = true;
dragOffset.x = e.clientX - panel.offsetLeft;
dragOffset.y = e.clientY - panel.offsetTop;
header.style.cursor = 'grabbing';
document.body.style.userSelect = 'none'; // 防止选中文本
e.preventDefault();
};
}
// 悬浮宠物拖拽
if (pet) {
pet.onmousedown = (e) => {
if (e.detail === 1) { // 单击时不拖拽,双击时拖拽
setTimeout(() => {
if (e.detail === 1) return; // 如果是单击就返回
isDragging = true;
dragOffset.x = e.clientX - pet.offsetLeft;
dragOffset.y = e.clientY - pet.offsetTop;
pet.style.cursor = 'grabbing';
document.body.style.userSelect = 'none';
e.preventDefault();
e.stopPropagation();
}, 200);
}
};
}
// 优化的鼠标移动事件(使用requestAnimationFrame)
let animationId = null;
document.onmousemove = (e) => {
if (isDragging) {
if (animationId) {
cancelAnimationFrame(animationId);
}
animationId = requestAnimationFrame(() => {
if (isDragging) {
const activeElement = panel.style.display !== 'none' ? panel : pet;
if (activeElement) {
const newX = e.clientX - dragOffset.x;
const newY = e.clientY - dragOffset.y;
// 限制在屏幕范围内
const maxX = window.innerWidth - activeElement.offsetWidth;
const maxY = window.innerHeight - activeElement.offsetHeight;
activeElement.style.left = Math.max(0, Math.min(newX, maxX)) + 'px';
activeElement.style.top = Math.max(0, Math.min(newY, maxY)) + 'px';
activeElement.style.right = 'auto';
activeElement.style.bottom = 'auto';
}
}
});
}
};
// 全局鼠标释放事件
document.onmouseup = () => {
if (isDragging) {
isDragging = false;
if (header) header.style.cursor = 'move';
if (pet) pet.style.cursor = 'pointer';
document.body.style.userSelect = '';
}
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null;
}
};
}
// 最小化面板
function minimizePanel() {
const panel = document.getElementById('knowledgePanel');
const pet = document.getElementById('floatingPet');
if (panel && pet) {
panel.style.display = 'none';
pet.style.display = 'flex';
// 悬浮宠物显示状态
if (stats.processed > 0) {
const accuracy = Math.round((stats.success / stats.processed) * 100);
pet.innerHTML = `${accuracy}%`;
pet.title = `答题进度: ${stats.processed}/${stats.total} (${accuracy}%) - 点击展开`;
} else {
pet.innerHTML = '📚';
pet.title = '知识库答题助手 - 点击展开';
}
log('📱 已最小化为悬浮小宠物');
}
}
// 恢复面板
function restorePanel() {
const panel = document.getElementById('knowledgePanel');
const pet = document.getElementById('floatingPet');
if (panel && pet) {
panel.style.display = 'block';
pet.style.display = 'none';
log('📱 已恢复面板显示');
}
}
// 关闭面板
function closePanel() {
const panel = document.getElementById('knowledgePanel');
const pet = document.getElementById('floatingPet');
if (confirm('确定要关闭知识库答题助手吗?')) {
if (panel) panel.remove();
if (pet) pet.remove();
// 停止答题
CONFIG.stop = true;
log('❌ 答题助手已关闭');
console.log('📚 知识库答题助手已关闭');
}
}
// 初始化
function init() {
if (!location.href.includes('txsyaqpx.zhongancloud.com')) {
return;
}
log('🚀 知识库答题助手已启动');
const checkReady = () => {
if (document.querySelector('.ques-type-item')) {
log('✅ 页面加载完成');
createPanel();
} else {
setTimeout(checkReady, 1000);
}
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', checkReady);
} else {
setTimeout(checkReady, 1000);
}
}
// 启动
init();
})();