// ==UserScript== // @name 小说阅读器 (极简稳定版) // @namespace http://tampermonkey.net/ // @version 1.0 // @description 回归初心,最简单的样式。右下角固定一个小按钮开关,也可以用 Alt+M。 // @author Gemini // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @connect * // @downloadURL https://update.greasyfork.icu/scripts/575624/%E5%B0%8F%E8%AF%B4%E9%98%85%E8%AF%BB%E5%99%A8%20%28%E6%9E%81%E7%AE%80%E7%A8%B3%E5%AE%9A%E7%89%88%29.user.js // @updateURL https://update.greasyfork.icu/scripts/575624/%E5%B0%8F%E8%AF%B4%E9%98%85%E8%AF%BB%E5%99%A8%20%28%E6%9E%81%E7%AE%80%E7%A8%B3%E5%AE%9A%E7%89%88%29.meta.js // ==/UserScript== (function() { 'use strict'; // 防止在 iframe 中无限嵌套 if (window.top !== window.self) return; // --- 1. 创建一个永远可见的实体开关按钮 --- const toggleBtn = document.createElement('button'); toggleBtn.textContent = '📚'; toggleBtn.title = '打开/关闭阅读器'; toggleBtn.style.cssText = ` position: fixed; bottom: 20px; right: 20px; z-index: 2147483647; padding: 5px 10px; cursor: pointer; border: 1px solid #ccc; background: white; border-radius: 4px; opacity: 0.6; font-size: 16px; `; document.body.appendChild(toggleBtn); // --- 2. 创建最简单的主容器 --- const container = document.createElement('div'); container.style.cssText = ` position: fixed; bottom: 60px; right: 20px; width: 350px; height: 500px; background: white; border: 1px solid #ccc; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 2147483647; display: none; /* 默认隐藏 */ flex-direction: column; resize: both; overflow: hidden; opacity: 0.85; font-family: sans-serif; `; document.body.appendChild(container); // --- 3. 顶部控制栏 (只保留输入框、按钮和透明度滑块) --- const header = document.createElement('div'); header.style.cssText = 'padding: 6px; background: #f8f9fa; border-bottom: 1px solid #ddd; display: flex; gap: 5px; align-items: center;'; const urlInput = document.createElement('input'); urlInput.placeholder = '输入网址...'; urlInput.style.cssText = 'flex-grow: 1; padding: 4px; font-size: 12px; border: 1px solid #ccc;'; urlInput.value = GM_getValue('moyu_last_url', ''); const loadBtn = document.createElement('button'); loadBtn.textContent = '加载'; loadBtn.style.cssText = 'padding: 4px 8px; font-size: 12px; cursor: pointer; background: white; border: 1px solid #ccc;'; const opacityInput = document.createElement('input'); opacityInput.type = 'range'; opacityInput.min = '0.1'; opacityInput.max = '1'; opacityInput.step = '0.05'; opacityInput.value = '0.85'; opacityInput.style.cssText = 'width: 60px; cursor: pointer;'; header.appendChild(urlInput); header.appendChild(loadBtn); header.appendChild(opacityInput); // --- 4. 内容区 --- const iframe = document.createElement('iframe'); iframe.style.cssText = 'width: 100%; flex-grow: 1; border: none; background: #fff;'; container.appendChild(header); container.appendChild(iframe); // --- 5. 核心加载逻辑 --- const loadUrl = () => { let url = urlInput.value.trim(); if (!url) return; if (!url.startsWith('http')) url = 'https://' + url; loadBtn.textContent = '...'; GM_xmlhttpRequest({ method: "GET", url: url, headers: { "User-Agent": navigator.userAgent, "Referer": new URL(url).origin + "/" }, onload: (res) => { loadBtn.textContent = '加载'; if(res.status !== 200) { iframe.srcdoc = `