// ==UserScript== // @name USCardForum AI 总结 (v39.0 智能对话版) // @namespace http://tampermonkey.net/ // @version 39.0 // @description 总结后自动生成聊天模式,支持基于上下文的连续追问 // @author ALousaBao // @match https://www.uscardforum.com/* // @connect generativelanguage.googleapis.com // @connect uscardforum.com // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @updateURL https://raw.githubusercontent.com/nitan-ALousaBao/nitan-AI-summary/main/nitan-ai-summary.js // @downloadURL https://raw.githubusercontent.com/nitan-ALousaBao/nitan-AI-summary/main/nitan-ai-summary.js // ==/UserScript== (function() { 'use strict'; // ✅ 你的 API Key const API_KEY = ''; // 🎨 聊天样式注入 GM_addStyle(` .ai-progress-container { width: 100%; height: 4px; background: #f0f0f0; margin-bottom: 10px; border-radius: 2px; overflow: hidden; display: none; } .ai-progress-bar { width: 0%; height: 100%; background: #28a745; transition: width 0.2s ease; } /* 按钮组 */ .ai-btn-group { display: flex; flex-direction: column; gap: 8px; align-items: flex-end; } .ai-btn { padding: 8px 16px; color: white; border: 1px solid rgba(255,255,255,0.5); border-radius: 50px; cursor: pointer; font-weight: bold; font-size: 13px; box-shadow: 0 4px 8px rgba(0,0,0,0.2); transition: transform 0.1s; min-width: 140px; font-family: sans-serif; } .ai-btn:hover { transform: scale(1.05); } .ai-btn:active { transform: scale(0.95); } /* 聊天气泡 */ .chat-bubble { max-width: 85%; padding: 10px 14px; border-radius: 12px; margin-bottom: 10px; font-size: 14px; line-height: 1.5; word-wrap: break-word; position: relative; } .chat-user { align-self: flex-end; background-color: #0088cc; color: white; border-bottom-right-radius: 2px; } .chat-ai { align-self: flex-start; background-color: #f1f3f5; color: #333; border-bottom-left-radius: 2px; border: 1px solid #e0e0e0; } .chat-system { align-self: center; font-size: 12px; color: #999; margin: 5px 0; font-style: italic; } /* 输入区域 */ .chat-input-area { display: flex; gap: 8px; padding: 12px; border-top: 1px solid #eee; background: white; border-radius: 0 0 12px 12px; } .chat-textarea { flex-grow: 1; padding: 8px; border: 1px solid #ddd; border-radius: 8px; resize: none; height: 40px; font-family: inherit; font-size: 14px; outline: none; transition: border 0.2s; } .chat-textarea:focus { border-color: #0088cc; } .chat-send-btn { width: 60px; height: 40px; background: #0088cc; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; } .chat-send-btn:hover { background: #0077b3; } .chat-send-btn:disabled { background: #ccc; cursor: not-allowed; } `); // 状态管理 let currentModel = GM_getValue('ai_model_selection', null); let currentLang = localStorage.getItem('ai_summary_lang') || 'zh'; let availableModels = []; let chatHistory = []; // 存储对话上下文 let isGenerating = false; const CONTAINER_ID = 'ai-btn-container-v39'; const BOX_ID = 'ai-chat-window-v39'; // 🌐 语言包 const I18N = { zh: { ui_title: "🤖 AI 助手", btn_settings: "⚙️ 设置", btn_close: "✕", input_placeholder: "继续追问... (Enter发送)", btn_send: "发送", status_init: "🔄 初始化...", status_thinking: "🤖 正在思考...", prompt_lang: "请严格使用简体中文输出。", prompt_prefix: "你是一个美卡论坛助手。", tag_rec: "🟢 推荐", // 按钮 btn_search_ultra: "🤯 究极搜索 (Top 10)", btn_search_deep: "🧠 深度搜索 (Top 50)", btn_search_fast: "⚡ 屏幕总结", btn_topic_full: "🧠 深度全帖 (并发)", btn_topic_medium: "⚖️ 中度分析 (首尾)", btn_topic_fast: "⚡ 快速总结", // 提示 err_net: "网络错误", err_429: "❌ 速度太快 (429),请稍候...", }, en: { ui_title: "🤖 AI Assistant", btn_settings: "⚙️ Settings", btn_close: "✕", input_placeholder: "Ask follow-up... (Enter to send)", btn_send: "Send", status_init: "🔄 Init...", status_thinking: "🤖 Thinking...", prompt_lang: "Please output strictly in ENGLISH.", prompt_prefix: "You are a forum assistant.", tag_rec: "🟢 Rec.", // Buttons btn_search_ultra: "🤯 Ultra Search (Top 10)", btn_search_deep: "🧠 Deep Search (Top 50)", btn_search_fast: "⚡ Screen Summary", btn_topic_full: "🧠 Deep Full-Topic", btn_topic_medium: "⚖️ Medium Analysis", btn_topic_fast: "⚡ Fast Summary", // Errors err_net: "Network Error", err_429: "❌ Rate Limit (429)", } }; const t = (key) => I18N[currentLang][key] || key; // === 1. 初始化 === initModelList(); // === 2. 界面监控 === setInterval(() => { const url = window.location.href; const valid = (url.includes('/search') && document.querySelector('.fps-result')) || (url.includes('/t/') && document.querySelector('.post-stream')); if (valid) { if (!document.getElementById(CONTAINER_ID)) createMainUI(); } else { const c = document.getElementById(CONTAINER_ID); if(c) c.remove(); } }, 1000); // === 3. UI 构建 === function createMainUI() { if(document.getElementById(CONTAINER_ID)) return; const c = document.createElement('div'); c.id = CONTAINER_ID; c.className = 'ai-btn-group'; c.style.cssText = `position: fixed !important; bottom: 40px; right: 40px; z-index: 999999;`; // 工具栏 const toolbar = document.createElement('div'); toolbar.style.cssText = "display:flex; gap:5px;"; const langSel = document.createElement('select'); langSel.style.cssText = "padding:4px;border-radius:8px;font-size:12px;border:1px solid #ccc;cursor:pointer;"; langSel.innerHTML = ``; langSel.onchange = (e) => { currentLang = e.target.value; localStorage.setItem('ai_summary_lang', currentLang); updateMainUI(); }; const settingsBtn = document.createElement('button'); settingsBtn.innerHTML = t('btn_settings'); settingsBtn.style.cssText = "padding:4px 8px;border-radius:8px;font-size:12px;cursor:pointer;border:1px solid #ccc;background:#f8f9fa;"; settingsBtn.onclick = () => alert("当前模型: " + currentModel); // 简化设置,点击显示当前模型 toolbar.appendChild(langSel); toolbar.appendChild(settingsBtn); c.appendChild(toolbar); // 按钮逻辑 const isSearch = window.location.href.includes('/search'); if (isSearch) { c.appendChild(createBtn(t('btn_search_ultra'), '#dc3545', handleSearchUltra)); c.appendChild(createBtn(t('btn_search_deep'), '#6f42c1', handleSearchDeep)); c.appendChild(createBtn(t('btn_search_fast'), '#0088cc', handleSearchFast)); } else { c.appendChild(createBtn(t('btn_topic_full'), '#dc3545', handleTopicFull)); c.appendChild(createBtn(t('btn_topic_medium'), '#6f42c1', handleTopicMedium)); c.appendChild(createBtn(t('btn_topic_fast'), '#fd7e14', handleTopicFast)); } document.body.appendChild(c); } function createBtn(text, color, onClick) { const b = document.createElement('button'); b.className = 'ai-btn'; b.innerHTML = text; b.style.background = color; b.onclick = onClick; return b; } function updateMainUI() { const old = document.getElementById(CONTAINER_ID); if(old) old.remove(); createMainUI(); } // === 4. 聊天窗口 UI === function openChatWindow(initialLoadingText) { let box = document.getElementById(BOX_ID); if (!box) { box = document.createElement('div'); box.id = BOX_ID; box.style.cssText = `position: fixed; top: 10%; right: 10%; width: 500px; height: 75vh; background: white; z-index: 1000000; border-radius: 12px; box-shadow: 0 25px 80px rgba(0,0,0,0.5); font-family: -apple-system, sans-serif; border: 1px solid #ccc; display: flex; flex-direction: column;`; // Header const header = document.createElement('div'); header.style.cssText = `padding:12px 20px;border-bottom:1px solid #eee;background:#f8f9fa;border-radius:12px 12px 0 0;display:flex;justify-content:space-between;align-items:center;flex-shrink:0;`; header.innerHTML = `${t('ui_title')}`; const close = document.createElement('button'); close.innerText = t('btn_close'); close.style.cssText = "border:none;background:none;font-size:16px;cursor:pointer;color:#666;"; close.onclick = () => box.style.display = 'none'; header.appendChild(close); box.appendChild(header); // Progress Bar const prog = document.createElement('div'); prog.id = BOX_ID + '_prog'; prog.className = 'ai-progress-container'; prog.innerHTML = `
`; box.appendChild(prog); // Chat Content Area const content = document.createElement('div'); content.id = BOX_ID + '_content'; content.style.cssText = `padding:20px;overflow-y:auto;flex-grow:1;background:#fff;display:flex;flex-direction:column;gap:5px;`; box.appendChild(content); // Input Area const inputArea = document.createElement('div'); inputArea.className = 'chat-input-area'; inputArea.innerHTML = ` `; box.appendChild(inputArea); document.body.appendChild(box); // Bind Events document.getElementById('ai-chat-send').onclick = sendUserMessage; document.getElementById('ai-chat-input').addEventListener('keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendUserMessage(); } }); } box.style.display = 'flex'; // Clear history for new task const contentDiv = document.getElementById(BOX_ID + '_content'); contentDiv.innerHTML = ''; appendSystemMessage(initialLoadingText); // Disable input while loading toggleInput(false); } // === 5. 消息处理 === function appendMessage(role, text) { const div = document.createElement('div'); div.className = `chat-bubble chat-${role}`; if (role === 'ai') { // Markdown简单处理 div.innerHTML = text.replace(/\*\*(.*?)\*\*/g, '$1').replace(/\n/g, '