您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Settings module for Text Explainer
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/528763/1547018/Text%20Explainer%20Settings.js
// ==UserScript== // @name Text Explainer Settings // @namespace http://tampermonkey.net/ // @version 0.1.0 // @description Settings module for Text Explainer // @author RoCry // @license MIT // ==/UserScript== class TextExplainerSettings { constructor(defaultConfig = {}) { this.defaultConfig = Object.assign({ model: "gemini-2.0-flash", apiKey: null, baseUrl: "https://generativelanguage.googleapis.com", provider: "gemini", language: "Chinese" }, defaultConfig); this.config = this.load(); } /** * Load settings from storage */ load() { try { const savedConfig = typeof GM_getValue === 'function' ? GM_getValue('explainerConfig', {}) : JSON.parse(localStorage.getItem('explainerConfig') || '{}'); return Object.assign({}, this.defaultConfig, savedConfig); } catch (e) { console.error('Error loading settings:', e); return Object.assign({}, this.defaultConfig); } } /** * Save settings to storage */ save() { try { if (typeof GM_setValue === 'function') { GM_setValue('explainerConfig', this.config); } else { localStorage.setItem('explainerConfig', JSON.stringify(this.config)); } return true; } catch (e) { console.error('Error saving settings:', e); return false; } } /** * Get setting value */ get(key) { return this.config[key]; } /** * Set setting value */ set(key, value) { this.config[key] = value; return this; } /** * Update multiple settings at once */ update(settings) { Object.assign(this.config, settings); return this; } /** * Reset settings to defaults */ reset() { this.config = Object.assign({}, this.defaultConfig); return this; } /** * Get all settings */ getAll() { return Object.assign({}, this.config); } /** * Open settings dialog */ openDialog(onSave = null) { // First check if dialog already exists and remove it const existingDialog = document.getElementById('explainer-settings-dialog'); if (existingDialog) existingDialog.remove(); // Create dialog container const dialog = document.createElement('div'); dialog.id = 'explainer-settings-dialog'; dialog.style = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 16px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); z-index: 10001; width: 400px; max-width: 90vw; font-family: system-ui, sans-serif; `; // Add dark mode support const styleElement = document.createElement('style'); styleElement.textContent = ` #explainer-settings-dialog { color: #333; } #explainer-settings-dialog label { display: block; margin: 12px 0 4px; font-weight: 500; } #explainer-settings-dialog input[type="text"], #explainer-settings-dialog select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; font-size: 14px; } #explainer-settings-dialog .buttons { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; } #explainer-settings-dialog button { padding: 8px 12px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; } #explainer-settings-dialog button.primary { background-color: #4285f4; color: white; } #explainer-settings-dialog button.secondary { background-color: #f1f1f1; color: #333; } @media (prefers-color-scheme: dark) { #explainer-settings-dialog { background: #333; color: #eee; } #explainer-settings-dialog input[type="text"], #explainer-settings-dialog select { background: #444; color: #eee; border-color: #555; } #explainer-settings-dialog button.secondary { background-color: #555; color: #eee; } } `; document.head.appendChild(styleElement); // Create dialog content dialog.innerHTML = ` <h3 style="margin-top:0;">Text Explainer Settings</h3> <div> <label for="explainer-language">Language</label> <select id="explainer-language"> <option value="Chinese" ${this.config.language === 'Chinese' ? 'selected' : ''}>Chinese</option> <option value="English" ${this.config.language === 'English' ? 'selected' : ''}>English</option> <option value="Japanese" ${this.config.language === 'Japanese' ? 'selected' : ''}>Japanese</option> </select> </div> <div> <label for="explainer-provider">Provider</label> <select id="explainer-provider"> <option value="gemini" ${this.config.provider === 'gemini' ? 'selected' : ''}>Gemini</option> <option value="openai" ${this.config.provider === 'openai' ? 'selected' : ''}>OpenAI</option> <option value="anthropic" ${this.config.provider === 'anthropic' ? 'selected' : ''}>Anthropic</option> </select> </div> <div> <label for="explainer-model">Model</label> <input id="explainer-model" type="text" value="${this.config.model}"> </div> <div> <label for="explainer-api-key">API Key</label> <input id="explainer-api-key" type="text" value="${this.config.apiKey || ''}"> </div> <div> <label for="explainer-base-url">API Base URL</label> <input id="explainer-base-url" type="text" value="${this.config.baseUrl}"> </div> <div class="buttons"> <button id="explainer-settings-cancel" class="secondary">Cancel</button> <button id="explainer-settings-save" class="primary">Save</button> </div> `; document.body.appendChild(dialog); // Add event listeners document.getElementById('explainer-settings-save').addEventListener('click', () => { // Update config with form values this.update({ language: document.getElementById('explainer-language').value, model: document.getElementById('explainer-model').value, apiKey: document.getElementById('explainer-api-key').value, baseUrl: document.getElementById('explainer-base-url').value, provider: document.getElementById('explainer-provider').value }); // Save to storage this.save(); // Remove dialog dialog.remove(); styleElement.remove(); // Call save callback if provided if (typeof onSave === 'function') { onSave(this.config); } }); document.getElementById('explainer-settings-cancel').addEventListener('click', () => { dialog.remove(); styleElement.remove(); }); // Focus first field document.getElementById('explainer-language').focus(); } } // Make available globally and as a module if needed window.TextExplainerSettings = TextExplainerSettings; if (typeof module !== 'undefined') { module.exports = TextExplainerSettings; }