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();
})();