您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Settings module for Text Explainer
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/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;
- }