// ==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 = `
加载失败,状态码: ${res.status}
`; return; } let html = res.responseText; const baseTag = ``; const script = ``; if(html.includes('')) { html = html.replace('', `${baseTag}`); } else { html = baseTag + html; } iframe.srcdoc = html + script; GM_setValue('moyu_last_url', url); }, onerror: () => { loadBtn.textContent = '加载'; iframe.srcdoc = '
网络请求失败
'; } }); }; // --- 6. 事件绑定 --- loadBtn.onclick = loadUrl; urlInput.onkeypress = (e) => { if(e.key === 'Enter') loadUrl(); }; // 透明度实时调节 opacityInput.oninput = (e) => { container.style.opacity = e.target.value; }; // 拦截内部跳转 window.addEventListener('message', (e) => { if(e.data && e.data.type === 'NAV') { urlInput.value = e.data.url; loadUrl(); } }); // --- 7. 开关逻辑 --- const toggle = () => { container.style.display = container.style.display === 'none' ? 'flex' : 'none'; if(container.style.display === 'flex' && urlInput.value && !iframe.srcdoc) loadUrl(); }; // 按钮点击开关 toggleBtn.onclick = toggle; // 快捷键开关 (Alt+M 作为辅助) document.addEventListener('keydown', (e) => { if (e.altKey && e.key.toLowerCase() === 'm') toggle(); }); })();