// ==UserScript== // @name 通用广告屏蔽 // @namespace http://tampermonkey.net/ // @version 1.1 // @description 实时屏蔽网站的广告元素,支持可视化自定义选择器 // @author bbbyqq // @license MIT // @match *://*/* // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @downloadURL https://update.greasyfork.icu/scripts/532260/%E9%80%9A%E7%94%A8%E5%B9%BF%E5%91%8A%E5%B1%8F%E8%94%BD.user.js // @updateURL https://update.greasyfork.icu/scripts/532260/%E9%80%9A%E7%94%A8%E5%B9%BF%E5%91%8A%E5%B1%8F%E8%94%BD.meta.js // ==/UserScript== (function() { 'use strict'; // 默认隐藏列表 const DEFAULT_HIDE_LIST = [ '.ad', '#ad' ]; // 从存储中获取或初始化隐藏列表 let hideList = GM_getValue('hideList', DEFAULT_HIDE_LIST); // 定义隐藏广告函数 function hideAds() { hideList.forEach(item => { try { document.querySelectorAll(item).forEach(ad => { ad.style.display = 'none'; }); } catch (e) { console.error('Error hiding ads with selector:', item, e); } }); } // 初始执行隐藏 hideAds(); // 创建MutationObserver监听DOM变化 const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.addedNodes.length) { hideAds(); } }); }); // 开始监听body及其子元素变化 observer.observe(document.body, { childList: true, subtree: true, attributes: false, characterData: false }); // 添加自定义样式 GM_addStyle(` /* 弹窗基础样式 */ #adBlockCustomDialog { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 500px; max-width: 90%; background: #ffffff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); z-index: 999999; display: none; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; color: #333; } /* 弹窗头部 */ #adBlockCustomDialog .dialog-header { padding: 16px 20px; background: #f8f9fa; border-bottom: 1px solid #e9ecef; font-size: 18px; font-weight: 600; display: flex; justify-content: space-between; align-items: center; } /* 弹窗内容区域 */ #adBlockCustomDialog .dialog-body { padding: 20px; overflow-y: auto; max-height: calc(80vh - 130px); } /* 弹窗底部 */ #adBlockCustomDialog .dialog-footer { padding: 16px 20px; background: #f8f9fa; border-top: 1px solid #e9ecef; display: flex; justify-content: space-between; align-items: center; } /* 规则列表容器 */ #adBlockCustomDialog .rule-list { margin-bottom: 20px; } /* 单个规则项 */ #adBlockCustomDialog .rule-item { display: flex; margin-bottom: 10px; align-items: center; gap: 10px; } /* 规则输入框 */ #adBlockCustomDialog .rule-item input { flex: 1; padding: 10px 12px; border: 1px solid #ced4da; border-radius: 4px; font-size: 14px; transition: border-color 0.15s; } #adBlockCustomDialog .rule-item input:focus { border-color: #80bdff; outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } /* 删除规则按钮 */ #adBlockCustomDialog .rule-item button { padding: 10px 14px; background: #dc3545; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; transition: background-color 0.15s; } #adBlockCustomDialog .rule-item button:hover { background: #c82333; } /* 添加规则按钮 */ #adBlockCustomDialog .add-rule-btn { padding: 10px 16px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: 500; transition: background-color 0.15s; } #adBlockCustomDialog .add-rule-btn:hover { background: #218838; } /* 关闭按钮 */ #adBlockCustomDialog .dialog-close { background: none; border: none; font-size: 24px; cursor: pointer; color: #6c757d; padding: 0; line-height: 1; } #adBlockCustomDialog .dialog-close:hover { color: #495057; } /* 通用按钮样式 */ #adBlockCustomDialog .btn { padding: 10px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.15s; } /* 主要按钮(保存) */ #adBlockCustomDialog .btn-primary { background: #007bff; color: white; } #adBlockCustomDialog .btn-primary:hover { background: #0069d9; } /* 次要按钮(取消) */ #adBlockCustomDialog .btn-secondary { background: #6c757d; color: white; } #adBlockCustomDialog .btn-secondary:hover { background: #5a6268; } /* 危险按钮(重置) */ #adBlockCustomDialog .btn-danger { background: #dc3545; color: white; } #adBlockCustomDialog .btn-danger:hover { background: #c82333; } /* 按钮组 */ #adBlockCustomDialog .btn-group { display: flex; gap: 10px; height: fit-content; } /* 遮罩层 */ #adBlockOverlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 999998; display: none; } `); // 创建自定义弹窗 function createCustomDialog() { // 创建遮罩层 const overlay = document.createElement('div'); overlay.id = 'adBlockOverlay'; // 创建对话框 const dialog = document.createElement('div'); dialog.id = 'adBlockCustomDialog'; // 对话框头部 const header = document.createElement('div'); header.className = 'dialog-header'; header.innerHTML = ` 广告屏蔽规则管理 `; // 对话框主体 const body = document.createElement('div'); body.className = 'dialog-body'; // 规则列表容器 const ruleList = document.createElement('div'); ruleList.className = 'rule-list'; // 对话框底部 const footer = document.createElement('div'); footer.className = 'dialog-footer'; // 创建按钮组(右侧按钮) const btnGroup = document.createElement('div'); btnGroup.className = 'btn-group'; // 添加规则按钮(现在在footer中) const addButton = document.createElement('button'); addButton.className = 'add-rule-btn'; addButton.textContent = '+ 添加新规则'; // 取消按钮 const cancelBtn = document.createElement('button'); cancelBtn.className = 'btn btn-secondary'; cancelBtn.id = 'cancelChanges'; cancelBtn.textContent = '取消'; // 保存按钮 const saveBtn = document.createElement('button'); saveBtn.className = 'btn btn-primary'; saveBtn.id = 'saveRules'; saveBtn.textContent = '保存'; // 重置按钮(左侧) const resetBtn = document.createElement('button'); resetBtn.className = 'btn btn-danger'; resetBtn.id = 'resetRules'; resetBtn.textContent = '重置为默认'; // 组装按钮组 btnGroup.appendChild(addButton); btnGroup.appendChild(cancelBtn); btnGroup.appendChild(saveBtn); // 组装footer footer.appendChild(resetBtn); footer.appendChild(btnGroup); // 组装对话框 body.appendChild(ruleList); dialog.appendChild(header); dialog.appendChild(body); dialog.appendChild(footer); document.body.appendChild(overlay); document.body.appendChild(dialog); // 关闭按钮事件 header.querySelector('.dialog-close').addEventListener('click', closeDialog); overlay.addEventListener('click', closeDialog); // 添加规则按钮事件 addButton.addEventListener('click', addNewRuleField); // 底部按钮事件 resetBtn.addEventListener('click', resetToDefault); cancelBtn.addEventListener('click', closeDialog); saveBtn.addEventListener('click', saveRules); // 填充现有规则 populateRuleList(); // 显示对话框 dialog.style.display = 'block'; overlay.style.display = 'block'; // 填充规则列表 function populateRuleList() { ruleList.innerHTML = ''; hideList.forEach((rule, index) => { addRuleField(rule, index); }); } // 添加规则输入框 function addRuleField(rule = '', index = null) { const ruleItem = document.createElement('div'); ruleItem.className = 'rule-item'; const input = document.createElement('input'); input.type = 'text'; input.value = rule; input.placeholder = '输入CSS选择器 (如 .ad-banner)'; const removeBtn = document.createElement('button'); removeBtn.textContent = '删除'; ruleItem.appendChild(input); ruleItem.appendChild(removeBtn); ruleList.appendChild(ruleItem); // 删除按钮事件 removeBtn.addEventListener('click', () => { ruleList.removeChild(ruleItem); }); } // 添加新规则输入框 function addNewRuleField() { addRuleField(); } // 重置为默认规则 function resetToDefault() { if (confirm('确定要重置为默认规则吗?这将丢失所有自定义规则。')) { hideList = [...DEFAULT_HIDE_LIST]; populateRuleList(); } } // 保存规则 function saveRules() { const inputs = ruleList.querySelectorAll('input'); const newRules = []; inputs.forEach(input => { const value = input.value.trim(); if (value) { newRules.push(value); } }); if (newRules.length === 0) { alert('至少需要一条规则!'); return; } hideList = newRules; GM_setValue('hideList', hideList); setTimeout(()=>{ location.reload() }, 500) } // 关闭对话框 function closeDialog() { dialog.style.display = 'none'; overlay.style.display = 'none'; document.body.removeChild(dialog); document.body.removeChild(overlay); } } // 注册菜单命令 if (window.self === window.top) { // 只在主窗口中注册菜单 GM_registerMenuCommand("管理广告屏蔽规则", createCustomDialog); } })();