NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name AermTab // @namespace http://tampermonkey.net/ // @version 1.0 // @license MIT // @description 错误新页标签--当打开的页面无法链接时打开搜索页 // @author YourName // @match *://*/* // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; // ====================== // 样式模块 // ====================== const injectStyles = () => { GM_addStyle(` :root { --primary-color: #4a90e2; --hover-color: #357abd; --danger-color: #ff4444; } body { font-family: 'Segoe UI', sans-serif; margin: 0; padding: 20px; background: #f0f2f5; } .container { max-width: 800px; margin: 0 auto; } header h1 { color: var(--primary-color); text-align: center; margin-bottom: 30px; } .search-box { display: flex; gap: 10px; margin-bottom: 20px; } #searchInput { flex: 1; padding: 12px 20px; border: 2px solid var(--primary-color); border-radius: 24px; font-size: 16px; transition: box-shadow 0.3s; } #searchInput:focus { outline: none; box-shadow: 0 0 8px rgba(74,144,226,0.3); } button { padding: 12px 24px; background: var(--primary-color); border: none; border-radius: 24px; color: white; cursor: pointer; transition: background 0.3s; } button:hover { background: var(--hover-color); } .links-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 15px; margin-top: 30px; } .link-card { display: flex; justify-content: space-between; align-items: center; padding: 12px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); transition: transform 0.2s; } .link-card:hover { transform: translateY(-2px); } .link-card a { color: var(--primary-color); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .delete-btn { color: var(--danger-color); cursor: pointer; padding: 4px; margin-left: 8px; } .history-panel { background: white; border-radius: 8px; padding: 15px; margin: 20px 0; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .history-item { display: inline-block; margin: 5px; padding: 6px 12px; background: #e3f2fd; border-radius: 15px; cursor: pointer; transition: background 0.3s; } .history-item:hover { background: #bbdefb; } `); }; // ====================== // 模板模块 // ====================== const pageTemplate = () => ` <div class="container"> <header> <h1>AermTab</h1> </header> <div class="search-box"> <input type="text" id="searchInput" placeholder="输入搜索内容..." autocomplete="off"> <button id="searchBtn">全网搜索</button> </div> <div class="history-panel"> <div id="searchHistory"></div> </div> <div class="links-grid" id="linkList"></div> </div> `; // ====================== // 核心功能模块 // ====================== class AermTab { constructor() { this.links = GM_getValue('aermtab-links', this.defaultLinks()); this.history = GM_getValue('aermtab-history', []); this.init(); } defaultLinks() { return [ { name: '百度', url: 'https://www.baidu.com' }, { name: 'GitHub', url: 'https://github.com' }, { name: 'MDN', url: 'https://developer.mozilla.org' }, { name: 'Vue', url: 'https://vuejs.org' } ]; } init() { if (!this.checkEnvironment()) return; this.renderUI(); injectStyles(); this.bindEvents(); this.registerMenu(); } checkEnvironment() { const validHosts = [ 'localhost', '127.0.0.1', 'chromewebdata', 'newtab' ]; return validHosts.includes(window.location.hostname.toLowerCase()); } renderUI() { document.documentElement.innerHTML = pageTemplate(); this.renderLinks(); this.renderHistory(); } renderLinks() { const container = document.getElementById('linkList'); container.innerHTML = this.links .map((link, index) => ` <div class="link-card"> <a href="${link.url}" target="_blank">${link.name}</a> <span class="delete-btn" data-index="${index}">×</span> </div> `) .join(''); } renderHistory() { const container = document.getElementById('searchHistory'); container.innerHTML = this.history .slice(0, 15) .map(term => ` <div class="history-item" data-term="${term}"> ${term} </div> `) .join(''); } bindEvents() { // 搜索功能 document.getElementById('searchBtn').addEventListener('click', () => this.performSearch()); document.getElementById('searchInput').addEventListener('keypress', e => { if (e.key === 'Enter') this.performSearch(); }); // 事件委托 document.body.addEventListener('click', e => { // 删除书签 if (e.target.classList.contains('delete-btn')) { this.deleteLink(parseInt(e.target.dataset.index)); } // 点击历史记录 if (e.target.classList.contains('history-item')) { this.searchTerm(e.target.dataset.term); } }); } performSearch() { const input = document.getElementById('searchInput'); const term = input.value.trim(); if (!term) return; // 更新搜索历史 this.history = [ term, ...this.history.filter(t => t !== term) ].slice(0, 30); GM_setValue('aermtab-history', this.history); window.location.href = `https://www.baidu.com/s?wd=${encodeURIComponent(term)}`; } searchTerm(term) { document.getElementById('searchInput').value = term; this.performSearch(); } deleteLink(index) { this.links.splice(index, 1); GM_setValue('aermtab-links', this.links); this.renderLinks(); } registerMenu() { GM_registerMenuCommand('添加快捷方式', () => { const name = prompt('输入网站名称:'); const url = prompt('输入网站地址:'); if (name && url) { this.links.push({ name, url }); GM_setValue('aermtab-links', this.links); this.renderLinks(); } }); GM_registerMenuCommand('清除搜索历史', () => { this.history = []; GM_setValue('aermtab-history', []); this.renderHistory(); }); } } // ====================== // 初始化 // ====================== if (window.location.protocol === 'chrome-extension:') return; new AermTab(); })();