吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5910|回复: 46
上一主题 下一主题
收起左侧

[其他原创] AI答题助手-浏览器插件

[复制链接]
跳转到指定楼层
楼主
backaxe 发表于 2025-6-8 15:04 回帖奖励
本帖最后由 backaxe 于 2025-6-8 16:08 编辑

安装步骤
  • 创建一个新文件夹,将所有文件保存到该文件夹中
  • 打开Chrome浏览器,访问 chrome://extensions/
  • 开启"开发者模式"
  • 点击"加载已解压的扩展程序",选择你的插件文件夹
  • 插件安装完成后,点击插件图标进行设置
使用方法
  • 配置API:点击插件图标,填入API地址和密钥
  • 选择文本:在任何网页上用鼠标选中题目文本
  • 分析题目:按快捷键开始分析
  • 查看结果:分析结果会显示在题目下方,包含答案和解析
特色功能
  • 🎯 智能识别:自动识别并格式化答案和解析部分
  • 🔄 实时反馈:显示加载状态和错误提示
  • 🎨 美观界面:现代化的UI设计,支持响应式布局
  • ⌨️ 快捷操作:支持Esc键关闭结果窗口
  • 🛡️ 错误处理:完善的错误提示和异常处理
插件已经配置了专业的提示词,会要求AI助手提供准确的答案和详细解析。你只需要根据你使用的AI服务商(如OpenAI、Claude、国内厂商等)调整API地址和认证方式即可使用。PS:插件完全通过claude.ai生成

[JavaScript] 纯文本查看 复制代码
// content.js
console.log('Content script loaded on:', window.location.href);

let isAnalyzing = false;
let currentShortcut = 'F2'; // 默认快捷键

// 初始化时获取快捷键设置
chrome.storage.sync.get(['shortcut'], function(result) {
    currentShortcut = result.shortcut || 'F2';
    console.log('Current shortcut set to:', currentShortcut);
});

// 监听存储变化,更新快捷键设置
chrome.storage.onChanged.addListener(function(changes, namespace) {
    if (changes.shortcut) {
        currentShortcut = changes.shortcut.newValue;
        console.log('Shortcut updated to:', currentShortcut);
    }
});

// 监听来自background script的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.log('Message received in content script:', request);
    
    if (request.action === 'analyzeSelectedText') {
        analyzeSelectedText();
        sendResponse({ received: true });
    }
    
    return true;
});

// 键盘事件监听
document.addEventListener('keydown', function(event) {
    console.log('Key pressed:', event.key, 'Current shortcut:', currentShortcut);
    
    // 检查是否是设置的功能键
    if (event.key === currentShortcut) {
        event.preventDefault();
        console.log('Shortcut key matched, analyzing text');
        analyzeSelectedText();
        return;
    }
    
    // 备用快捷键:Ctrl+Shift+A 或 Cmd+Shift+A
    if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'A') {
        event.preventDefault();
        console.log('Legacy shortcut detected');
        analyzeSelectedText();
        return;
    }
    
    // 额外的备用快捷键:Alt+Q
    if (event.altKey && event.key === 'q') {
        event.preventDefault();
        console.log('Alt+Q shortcut detected');
        analyzeSelectedText();
        return;
    }
}, true); // 使用捕获阶段确保优先处理

// 分析选中的文本
async function analyzeSelectedText() {
    console.log('analyzeSelectedText called, isAnalyzing:', isAnalyzing);
    
    if (isAnalyzing) {
        showNotification('正在分析中,请稍候...', 'warning');
        return;
    }

    const selectedText = window.getSelection().toString().trim();
    console.log('Selected text length:', selectedText.length);
    console.log('Selected text preview:', selectedText.substring(0, 100));
    
    if (!selectedText) {
        showNotification('请先用鼠标选中要分析的题目文本', 'error');
        return;
    }

    if (selectedText.length < 3) {
        showNotification('选中的文本太短,请选择完整的题目', 'warning');
        return;
    }

    isAnalyzing = true;
    
    // 显示加载状态
    const loadingElement = showLoadingIndicator();
    
    try {
        console.log('Sending message to background script');
        
        // 发送消息给background script进行AI分析
        chrome.runtime.sendMessage({
            action: 'analyzeText',
            text: selectedText
        }, (response) => {
            console.log('Response from background:', response);
            
            isAnalyzing = false;
            
            // 移除加载指示器
            if (loadingElement && loadingElement.parentNode) {
                loadingElement.remove();
            }
            
            if (chrome.runtime.lastError) {
                console.error('Runtime error:', chrome.runtime.lastError);
                showNotification('插件连接错误:' + chrome.runtime.lastError.message, 'error');
                return;
            }
            
            if (response && response.success) {
                displayAnalysisResult(selectedText, response.result);
            } else {
                const errorMsg = response?.error || '分析失败,请检查网络连接和API设置';
                showNotification(errorMsg, 'error');
            }
        });
    } catch (error) {
        console.error('Error in analyzeSelectedText:', error);
        isAnalyzing = false;
        if (loadingElement && loadingElement.parentNode) {
            loadingElement.remove();
        }
        showNotification('发生错误:' + error.message, 'error');
    }
}

// 显示加载指示器
function showLoadingIndicator() {
    const selection = window.getSelection();
    if (selection.rangeCount === 0) {
        // 如果没有选中文本,在右上角显示加载提示
        const loading = document.createElement('div');
        loading.className = 'ai-assistant-loading';
        loading.innerHTML = `
            <div class="loading-content">
                <div class="loading-spinner"></div>
                <span>AI正在分析中...</span>
            </div>
        `;
        
        loading.style.position = 'fixed';
        loading.style.top = '20px';
        loading.style.right = '20px';
        loading.style.zIndex = '10000';
        
        document.body.appendChild(loading);
        return loading;
    }
    
    const range = selection.getRangeAt(0);
    const rect = range.getBoundingClientRect();
    
    const loading = document.createElement('div');
    loading.className = 'ai-assistant-loading';
    loading.innerHTML = `
        <div class="loading-content">
            <div class="loading-spinner"></div>
            <span>AI正在分析中...</span>
        </div>
    `;
    
    loading.style.position = 'fixed';
    loading.style.left = rect.left + 'px';
    loading.style.top = (rect.bottom + window.scrollY + 10) + 'px';
    loading.style.zIndex = '10000';
    
    document.body.appendChild(loading);
    return loading;
}

// 显示分析结果
function displayAnalysisResult(originalText, analysisResult) {
    const selection = window.getSelection();
    let rect = { left: 100, bottom: 100 }; // 默认位置
    
    if (selection.rangeCount > 0) {
        const range = selection.getRangeAt(0);
        rect = range.getBoundingClientRect();
    }
    
    // 创建结果容器
    const resultContainer = document.createElement('div');
    resultContainer.className = 'ai-assistant-result';
    resultContainer.innerHTML = `
        <div class="result-header">
            <h4>&#129302; AI答题助手</h4>
            <button class="close-btn">×</button>
        </div>
        <div class="result-content">
            <div class="original-question">
                <h5>&#128221; 题目:</h5>
                <p>${originalText}</p>
            </div>
            <div class="analysis-result">
                <h5>&#128161; 分析结果:</h5>
                <div class="analysis-text">${formatAnalysisResult(analysisResult)}</div>
            </div>
        </div>
        <div class="result-footer">
            <small>按Esc键、点击×或按 ${currentShortcut} 键关闭</small>
        </div>
    `;
    
    // 设置位置
    resultContainer.style.position = 'fixed';
    resultContainer.style.left = Math.min(rect.left, window.innerWidth - 500) + 'px';
    resultContainer.style.top = (rect.bottom + window.scrollY + 10) + 'px';
    resultContainer.style.zIndex = '10001';
    
    document.body.appendChild(resultContainer);
    
    // 添加键盘事件监听
    const closeHandler = (e) => {
        if (e.key === 'Escape' || e.key === currentShortcut) {
            resultContainer.remove();
            document.removeEventListener('keydown', closeHandler);
        }
    };
    document.addEventListener('keydown', closeHandler);
    
    // 显示成功通知
    showNotification(`分析完成!使用了快捷键: ${currentShortcut}`, 'success');
}

// 格式化分析结果
function formatAnalysisResult(result) {
    // 简单的格式化,将换行转换为<br>,并识别答案和解析部分
    let formatted = result.replace(/\n/g, '<br>');
    
    // 尝试识别答案和解析部分
    formatted = formatted.replace(/答案[::]/g, '<strong style="color: #e74c3c;">答案:</strong>');
    formatted = formatted.replace(/解析[::]/g, '<strong style="color: #3498db;">解析:</strong>');
    
    return formatted;
}

// 显示通知
function showNotification(message, type = 'info') {
    console.log('Showing notification:', message, type);
    
    const notification = document.createElement('div');
    notification.className = `ai-assistant-notification ${type}`;
    notification.textContent = message;
    
    notification.style.position = 'fixed';
    notification.style.top = '20px';
    notification.style.right = '20px';
    notification.style.zIndex = '10002';
    
    document.body.appendChild(notification);
    
    // 3秒后自动移除
    setTimeout(() => {
        if (document.body.contains(notification)) {
            notification.remove();
        }
    }, 3000);
}

// 页面加载完成后显示初始化信息

//window.addEventListener('load', function() {
//    console.log('Page loaded, AI Assistant ready');
//    setTimeout(() => {
//        showNotification(`AI答题助手已就绪!快捷键: ${currentShortcut}`, 'info');
//   }, 1000);
//});

// 显示加载指示器
function showLoadingIndicator() {
    const selection = window.getSelection();
    if (selection.rangeCount === 0) return null;
    
    const range = selection.getRangeAt(0);
    const rect = range.getBoundingClientRect();
    
    const loading = document.createElement('div');
    loading.className = 'ai-assistant-loading';
    loading.innerHTML = `
        <div class="loading-content">
            <div class="loading-spinner"></div>
            <span>AI正在分析中...</span>
        </div>
    `;
    
    loading.style.position = 'fixed';
    loading.style.left = rect.left + 'px';
    loading.style.top = (rect.bottom + window.scrollY + 10) + 'px';
    loading.style.zIndex = '10000';
    
    document.body.appendChild(loading);
    return loading;
}

// 显示分析结果
function displayAnalysisResult(originalText, analysisResult) {
    const selection = window.getSelection();
    if (selection.rangeCount === 0) return;
    
    const range = selection.getRangeAt(0);
    const rect = range.getBoundingClientRect();
    
    // 创建结果容器
    const resultContainer = document.createElement('div');
    resultContainer.className = 'ai-assistant-result';
    resultContainer.innerHTML = `
        <div class="result-header">
            <h4>&#129302; AI答题助手</h4>
            <button class="close-btn">×</button>
        </div>
        <div class="result-content">
            <div class="original-question">
                <h5>&#128221; 题目:</h5>
                <p>${originalText}</p>
            </div>
            <div class="analysis-result">
                <h5>&#128161; 分析结果:</h5>
                <div class="analysis-text">${formatAnalysisResult(analysisResult)}</div>
            </div>
        </div>
        <div class="result-footer">
            <small>按Esc键或点击×关闭</small>
        </div>
    `;
    
    // 设置位置
    resultContainer.style.position = 'fixed';
    resultContainer.style.left = Math.min(rect.left, window.innerWidth - 500) + 'px';
    resultContainer.style.top = (rect.bottom + window.scrollY + 10) + 'px';
    resultContainer.style.zIndex = '10001';
    
    document.body.appendChild(resultContainer);
    
    // 添加键盘事件监听
    const closeHandler = (e) => {
        if (e.key === 'Escape') {
            resultContainer.remove();
            document.removeEventListener('keydown', closeHandler);
        }
    };
    document.addEventListener('keydown', closeHandler);
    
    // 5秒后自动显示提示
    setTimeout(() => {
        if (document.body.contains(resultContainer)) {
            showNotification('分析结果已显示,按Esc键可关闭', 'info');
        }
    }, 5000);
}

// 格式化分析结果
function formatAnalysisResult(result) {
    // 简单的格式化,将换行转换为<br>,并识别答案和解析部分
    let formatted = result.replace(/\n/g, '<br>');
    
    // 尝试识别答案和解析部分
    formatted = formatted.replace(/答案[::]/g, '<strong style="color: #e74c3c;">答案:</strong>');
    formatted = formatted.replace(/解析[::]/g, '<strong style="color: #3498db;">解析:</strong>');
    
    return formatted;
}

// 显示通知
function showNotification(message, type = 'info') {
    const notification = document.createElement('div');
    notification.className = `ai-assistant-notification ${type}`;
    notification.textContent = message;
    
    notification.style.position = 'fixed';
    notification.style.top = '20px';
    notification.style.right = '20px';
    notification.style.zIndex = '10002';
    
    document.body.appendChild(notification);
    
    // 3秒后自动移除
    setTimeout(() => {
        if (document.body.contains(notification)) {
            notification.remove();
        }
    }, 3000);
}


[JavaScript] 纯文本查看 复制代码
// background.js
console.log('Background script loaded');

// 监听来自content script的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.log('Message received in background:', request);
    
    if (request.action === 'analyzeText') {
        analyzeTextWithAI(request.text)
            .then(result => {
                console.log('Analysis result obtained');
                sendResponse({ success: true, result: result });
            })
            .catch(error => {
                console.error('Analysis error:', error);
                sendResponse({ success: false, error: error.message });
            });
        
        return true; // 保持消息通道开放用于异步响应
    }
    
    // 处理测试连接消息
    if (request.action === 'testConnection') {
        testAPIConnection(request.settings)
            .then(result => {
                sendResponse({ success: true, result: result });
            })
            .catch(error => {
                sendResponse({ success: false, error: error.message });
            });
        
        return true;
    }
});

// 插件安装时设置默认值
chrome.runtime.onInstalled.addListener(() => {
    console.log('Extension installed, setting up defaults');
    
    chrome.storage.sync.get(['shortcut', 'modelName'], function(result) {
        const updates = {};
        
        if (!result.shortcut) {
            updates.shortcut = 'F2';
        }
        if (!result.modelName) {
            updates.modelName = 'gpt-3.5-turbo';
        }
        
        if (Object.keys(updates).length > 0) {
            chrome.storage.sync.set(updates);
            console.log('Default settings applied:', updates);
        }
    });
});

// 测试API连接
async function testAPIConnection(settings) {
    const { apiUrl, apiKey, modelName, customModel } = settings;
    
    let actualModelName = modelName || 'gpt-3.5-turbo';
    if (modelName === 'custom' && customModel) {
        actualModelName = customModel;
    }
    
    const response = await fetch(apiUrl, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${apiKey}`
        },
        body: JSON.stringify({
            model: actualModelName,
            messages: [
                {
                    role: 'user',
                    content: '测试连接'
                }
            ],
            max_tokens: 10
        })
    });
    
    if (!response.ok) {
        throw new Error(`${response.status} ${response.statusText}`);
    }
    
    return actualModelName;
}

// 使用AI分析文本
async function analyzeTextWithAI(text) {
    // 获取存储的设置
    const settings = await chrome.storage.sync.get(['apiUrl', 'apiKey', 'modelName', 'customModel']);
    
    console.log('Settings retrieved:', { 
        hasApiUrl: !!settings.apiUrl, 
        hasApiKey: !!settings.apiKey, 
        modelName: settings.modelName 
    });
    
    if (!settings.apiUrl || !settings.apiKey) {
        throw new Error('请先在插件设置中配置API地址和密钥。点击插件图标进行设置。');
    }

    // 确定使用的模型名称
    let modelName = settings.modelName || 'gpt-3.5-turbo';
    if (modelName === 'custom' && settings.customModel) {
        modelName = settings.customModel;
    } else if (modelName === 'custom') {
        throw new Error('请设置自定义模型名称');
    }

    const prompt = `你是一个专业的答题助手。请针对用户提供的题目,给出准确的答案和详细的解析。回答格式应该包含两部分:答案和解析。

题目内容:
${text}`;

    console.log('Making API request to:', settings.apiUrl, 'with model:', modelName);

    try {
        const response = await fetch(settings.apiUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${settings.apiKey}`
            },
            body: JSON.stringify({
                model: modelName,
                messages: [
                    {
                        role: 'user',
                        content: prompt
                    }
                ],
                max_tokens: 1000,
                temperature: 0.7
            })
        });

        console.log('API response status:', response.status);

        if (!response.ok) {
            const errorText = await response.text();
            console.error('API error response:', errorText);
            throw new Error(`API请求失败: ${response.status} ${response.statusText}`);
        }

        const data = await response.json();
        console.log('API response data keys:', Object.keys(data));
        
        if (data.choices && data.choices.length > 0) {
            return data.choices[0].message.content;
        } else {
            console.error('Unexpected API response format:', data);
            throw new Error('API返回数据格式异常,请检查API配置');
        }
    } catch (error) {
        console.error('AI分析错误:', error);
        if (error.name === 'TypeError' && error.message.includes('fetch')) {
            throw new Error('网络连接失败,请检查网络和API地址');
        }
        throw error;
    }
}

examHelper.zip

10.57 KB, 下载次数: 403, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 9吾爱币 +13 热心值 +8 收起 理由
lzbpp + 1 + 1 我很赞同!
yanglinman + 1 谢谢@Thanks!
cksincerely + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
陆仁嘉 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
MimzyGo + 1 + 1 热心回复!
开心熊猫741 + 1 + 1 谢谢@Thanks!
ma5635 + 1 + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
lijun888 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
苏紫方璇 发表于 2025-6-8 15:53
请在帖子中插入部分核心代码
本版块仅限分享编程技术和源码相关内容,发布帖子必须带上关键代码和具体功能介绍
推荐
conaneow 发表于 2025-6-9 00:26
4#
 楼主| backaxe 发表于 2025-6-8 16:09 |楼主
苏紫方璇 发表于 2025-6-8 15:53
请在帖子中插入部分核心代码
本版块仅限分享编程技术和源码相关内容,发布帖子必须带上关键代码和具体功能 ...

已修改,请版主审核
5#
dysunb 发表于 2025-6-8 21:07
分析结果会显示在题目下方
6#
ma5635 发表于 2025-6-8 21:15
可不可以搞个不用api的!
7#
An74123456 发表于 2025-6-8 21:42
感谢分享
8#
 楼主| backaxe 发表于 2025-6-8 22:09 |楼主
ma5635 发表于 2025-6-8 21:15
可不可以搞个不用api的!

国内各大云服务提供的模型服务免费额度的应该够用。
9#
 楼主| backaxe 发表于 2025-6-8 22:10 |楼主
dysunb 发表于 2025-6-8 21:07
分析结果会显示在题目下方

是的,也是第一次有这个想法,虽然现在考试的场景不多。
10#
DeFanta 发表于 2025-6-8 22:50
体验一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-4-17 04:04

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表