// ==UserScript== // @name AI Image Description Generator Gimini // @namespace http://tampermonkey.net/ // @version 1.0 // @description 使用AI生成网页图片描述 // @author AlphaCat // @match *://*/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 全局变量 let isSelectionMode = false; // 定义默认提示词 const DEFAULT_PROMPT = "Describe the image from the perspective of someone with only a kindergarten education. If it is a realistic photo, analyze the elements of aperture, focal length, and shutter separately from the perspective of a professional photographer and describe the subject matter of the photo."; // 添加样式 GM_addStyle(` .ai-config-modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); z-index: 10000; min-width: 500px; height: auto; } .ai-config-modal h3 { margin: 0 0 15px 0; font-size: 14px; font-weight: bold; color: #333; } .ai-config-modal label { display: inline-block; font-size: 12px; font-weight: bold; color: #333; margin: 0; line-height: normal; height: auto; } .ai-config-modal .input-wrapper { position: relative; display: flex; align-items: center; } .ai-config-modal input { display: block; width: 100%; padding: 2px 24px 2px 2px; margin: 2px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; line-height: normal; height: auto; box-sizing: border-box; } .ai-config-modal .input-icon { position: absolute; right: 4px; width: 16px; height: 16px; cursor: pointer; display: flex; align-items: center; justify-content: center; color: #666; font-size: 12px; user-select: none; } .ai-config-modal .clear-icon { right: 24px; } .ai-config-modal .toggle-password { right: 4px; } .ai-config-modal .input-icon:hover { color: #333; } .ai-config-modal .input-group { margin-bottom: 12px; height: auto; display: flex; flex-direction: column; } .ai-config-modal .button-row { display: flex; gap: 10px; align-items: center; margin-top: 5px; } .ai-config-modal .check-button { padding: 4px 8px; border: none; border-radius: 4px; background: #007bff; color: white; cursor: pointer; font-size: 12px; } .ai-config-modal .check-button:hover { background: #0056b3; } .ai-config-modal .check-button:disabled { background: #cccccc; cursor: not-allowed; } .ai-config-modal select { width: 100%; padding: 4px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; margin-top: 2px; } .ai-config-modal .status-text { font-size: 12px; margin-left: 10px; } .ai-config-modal .status-success { color: #28a745; } .ai-config-modal .status-error { color: #dc3545; } .ai-config-modal button { margin: 10px 5px; padding: 8px 15px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; } .ai-config-modal button#ai-save-config { background: #4CAF50; color: white; } .ai-config-modal button#ai-cancel-config { background: #dc3545; color: white; } .ai-config-modal button:hover { opacity: 0.9; } .ai-floating-btn { position: fixed; width: 32px; height: 32px; background: #4CAF50; color: white; border-radius: 50%; cursor: move; z-index: 9999; box-shadow: 0 2px 5px rgba(0,0,0,0.2); display: flex; align-items: center; justify-content: center; user-select: none; transition: background-color 0.3s; } .ai-floating-btn:hover { background: #45a049; } .ai-floating-btn svg { width: 20px; height: 20px; fill: white; } .ai-menu { position: absolute; background: white; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); padding: 8px; z-index: 10000; display: flex; gap: 8px; } .ai-menu-item { width: 32px; height: 32px; padding: 6px; cursor: pointer; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: background-color 0.3s; } .ai-menu-item:hover { background: #f5f5f5; } .ai-menu-item svg { width: 20px; height: 20px; fill: #666; } .ai-menu-item:hover svg { fill: #4CAF50; } .ai-image-options { display: flex; flex-direction: column; gap: 10px; margin: 15px 0; } .ai-image-options button { padding: 8px 15px; border: none; border-radius: 4px; background: #4CAF50; color: white; cursor: pointer; transition: background-color 0.3s; font-size: 14px; } .ai-image-options button:hover { background: #45a049; } #ai-cancel { background: #dc3545; color: white; } #ai-cancel:hover { opacity: 0.9; } .ai-toast { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); padding: 10px 20px; background: rgba(0, 0, 0, 0.8); color: white; border-radius: 4px; font-size: 14px; z-index: 10000; animation: fadeInOut 3s ease; pointer-events: none; white-space: pre-line; text-align: center; max-width: 80%; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } @keyframes fadeInOut { 0% { opacity: 0; transform: translate(-50%, 10px); } 10% { opacity: 1; transform: translate(-50%, 0); } 90% { opacity: 1; transform: translate(-50%, 0); } 100% { opacity: 0; transform: translate(-50%, -10px); } } .ai-config-modal .button-group { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; } .ai-config-modal .button-group button { padding: 6px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; transition: background-color 0.2s; } .ai-config-modal .save-button { background: #007bff; color: white; } .ai-config-modal .save-button:hover { background: #0056b3; } .ai-config-modal .save-button:disabled { background: #cccccc; cursor: not-allowed; } .ai-config-modal .cancel-button { background: #f8f9fa; color: #333; } .ai-config-modal .cancel-button:hover { background: #e2e6ea; } .ai-selecting-image { cursor: crosshair !important; } .ai-selecting-image * { cursor: crosshair !important; } .ai-image-description { position: fixed; background: rgba(0, 0, 0, 0.8); color: white; padding: 8px 12px; border-radius: 4px; font-size: 14px; line-height: 1.4; max-width: 300px; text-align: center; word-wrap: break-word; z-index: 10000; pointer-events: none; animation: fadeIn 0.3s ease; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .ai-modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 9999; } .ai-result-modal { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: relative; min-width: 300px; max-width: 1000px; max-height: 540px; overflow-y: auto; width: 90%; } .ai-result-modal h3 { margin: 0 0 10px 0; font-size: 14px; color: #333; } .ai-result-modal .description-code { background: #1e1e1e; color: #ffffff; padding: 12px; border-radius: 4px; margin: 5px 0; cursor: pointer; white-space: pre-wrap; word-wrap: break-word; font-family: monospace; border: 1px solid #333; position: relative; max-height: 500px; overflow-y: auto; font-size: 12px; line-height: 1.4; } .ai-result-modal .description-code * { color: #ffffff !important; } .ai-result-modal .description-code code { color: #ffffff; display: block; width: 100%; } .ai-result-modal .description-code:hover { background: #2d2d2d; color: #ffffff; } .ai-result-modal .copy-hint { font-size: 11px; color: #666; text-align: center; margin: 2px 0; } .ai-result-modal .close-button { position: absolute; top: 8px; right: 8px; background: none; border: none; font-size: 18px; cursor: pointer; color: #666; padding: 2px 6px; line-height: 1; } .ai-result-modal .close-button:hover { color: #333; } .ai-selection-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 9998; cursor: crosshair; pointer-events: none; } .ai-selecting-image img { position: relative; z-index: 9999; cursor: pointer !important; transition: outline 0.2s ease; } .ai-selecting-image img:hover { outline: 2px solid white; outline-offset: 2px; } /* 移动端样式优化 */ @media (max-width: 768px) { .ai-floating-btn { width: 40px; height: 40px; touch-action: none; } .ai-floating-btn svg { width: 24px; height: 24px; } .ai-config-modal { width: 90%; min-width: auto; max-width: 400px; padding: 15px; margin: 10px; box-sizing: border-box; } .ai-config-modal .button-group { margin-top: 15px; flex-direction: row; justify-content: space-between; gap: 10px; } .ai-config-modal .button-group button { flex: 1; min-height: 44px; font-size: 16px; padding: 10px; margin: 0; } .ai-result-modal { width: 95%; min-width: auto; max-width: 90%; margin: 10px; padding: 15px; } .ai-modal-overlay { padding: 10px; box-sizing: border-box; } .ai-config-modal button, .ai-config-modal .input-icon, .ai-config-modal select, .ai-config-modal input { min-height: 44px; padding: 10px; font-size: 16px; } .ai-config-modal textarea { min-height: 100px; font-size: 16px; padding: 10px; } .ai-config-modal .input-icon { width: 44px; height: 44px; font-size: 20px; } .ai-config-modal { max-height: 90vh; overflow-y: auto; -webkit-overflow-scrolling: touch; } } `); // 显示toast提示 function showToast(message, duration = 3000) { const toast = document.createElement('div'); toast.className = 'ai-toast'; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.remove(); }, duration); } // 进入图片选择模式 function enterImageSelectionMode() { if(isSelectionMode) return; isSelectionMode = true; const floatingBtn = document.querySelector('.ai-floating-btn'); if(floatingBtn) { floatingBtn.style.display = 'none'; } const overlay = document.createElement('div'); overlay.className = 'ai-selection-overlay'; document.body.appendChild(overlay); document.body.classList.add('ai-selecting-image'); const clickHandler = async function(e) { if (!isSelectionMode) return; if (e.target.tagName === 'IMG') { e.preventDefault(); e.stopPropagation(); showToast('图片选择功能待实现'); exitImageSelectionMode(); } }; document.addEventListener('click', clickHandler, true); const escHandler = (e) => { if (e.key === 'Escape') { exitImageSelectionMode(); } }; document.addEventListener('keydown', escHandler); window._imageSelectionHandlers = { click: clickHandler, keydown: escHandler }; } // 退出图片选择模式 function exitImageSelectionMode() { isSelectionMode = false; const floatingBtn = document.querySelector('.ai-floating-btn'); if(floatingBtn) { floatingBtn.style.display = 'flex'; } const overlay = document.querySelector('.ai-selection-overlay'); if (overlay) { overlay.remove(); } document.body.classList.remove('ai-selecting-image'); if (window._imageSelectionHandlers) { document.removeEventListener('click', window._imageSelectionHandlers.click, true); document.removeEventListener('keydown', window._imageSelectionHandlers.keydown); window._imageSelectionHandlers = null; } } // 创建配置界面 function createConfigUI() { const existingModal = document.querySelector('.ai-modal-overlay'); if (existingModal) { existingModal.remove(); } const overlay = document.createElement('div'); overlay.className = 'ai-modal-overlay'; const modal = document.createElement('div'); modal.className = 'ai-config-modal'; modal.innerHTML = `