您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
用于屏蔽幻想次元文章和评论
// ==UserScript== // @name 幻想次元黑名单脚本 // @namespace http://tampermonkey.net/ // @version 2025-04-08 // @description 用于屏蔽幻想次元文章和评论 // @author Aerry // @license MIT // @match http*://hxcy.top/* // @icon https://hxcy.top/wp-content/themes/wpdx/favicon.ico // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // ==/UserScript== (function () { 'use strict' // 初始化数据 const initData = () => { let data = localStorage.getItem('blockAuthor') if (!data) { data = { categories: ['默认', '低质量', '广告'], authors: [] } localStorage.setItem('blockAuthor', JSON.stringify(data)) } else { try { const parsedData = JSON.parse(data) // 检查是否是对象且包含authors数组 if (typeof parsedData === 'object' && parsedData !== null && Array.isArray(parsedData.authors)) { data = parsedData } else { // 如果数据格式不正确,重置为默认值 data = { categories: ['默认', '低质量', '广告'], authors: [] } localStorage.setItem('blockAuthor', JSON.stringify(data)) } } catch (e) { // 如果解析失败,也重置为默认值 data = { categories: ['默认', '低质量', '广告'], authors: [] } localStorage.setItem('blockAuthor', JSON.stringify(data)) } } return typeof data === 'string' ? JSON.parse(data) : data } // 保存数据 const saveData = (data) => { localStorage.setItem('blockAuthor', JSON.stringify(data)) } // 创建控制按钮 const createControlButton = () => { const btn = document.createElement('div') btn.id = 'togglePanelBtn' btn.innerHTML = '打开<br>面板' btn.style.position = 'fixed' btn.style.right = '20px' btn.style.bottom = '130px' btn.style.fontSize = '12px' btn.style.color = '#fff' btn.style.backgroundColor = '#323841' btn.style.width = '40px' btn.style.padding = '8px 0' btn.style.textAlign = 'center' btn.style.borderRadius = '2px' btn.style.zIndex = '1000' btn.style.cursor = 'pointer' document.body.appendChild(btn) return btn } // 创建面板 const createPanel = () => { const panel = document.createElement('div') panel.id = 'blockAuthorPanel' panel.style.display = 'none' // 默认隐藏 GM_addStyle(` @media screen and (max-width: 768px) { #togglePanelBtn { bottom: 85px !important; } } #blockAuthorPanel { position: fixed; top: 50px; right: 20px; width: 350px; background: #fff; border: 1px solid #ddd; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); z-index: 9999; padding: 15px; font-family: Arial, sans-serif; max-height: 80vh; overflow-y: auto; } #blockAuthorPanel h2 { margin-top: 0; padding-bottom: 10px; border-bottom: 1px solid #eee; font-size: 18px; display: flex; justify-content: space-between; align-items: center; } .close-panel { cursor: pointer; font-size: 20px; color: #999; } .close-panel:hover { color: #666; } .author-list { margin: 10px 0; } .author-item { display: flex; align-items: center; padding: 8px 0; border-bottom: 1px solid #f5f5f5; } .author-item:hover { background: #f9f9f9; } .author-name { flex-grow: 1; margin-left: 10px; } .category-tag { display: inline-block; padding: 2px 6px; background: #e1f5fe; border-radius: 3px; font-size: 12px; margin-left: 10px; color: #0288d1; } .panel-actions { display: flex; justify-content: space-between; margin-top: 15px; padding-top: 10px; border-top: 1px solid #eee; } .panel-btn { padding: 6px 12px; background: #f0f0f0; border: 1px solid #ddd; border-radius: 3px; cursor: pointer; } .panel-btn:hover { background: #e0e0e0; } .panel-btn.primary { background: #4CAF50; color: white; border-color: #4CAF50; } .panel-btn.danger { background: #f44336; color: white; border-color: #f44336; } .category-selector { margin-bottom: 15px; } .category-filter { margin-bottom: 10px; } .add-author-form { display: flex; margin-bottom: 15px; } .add-author-input { flex-grow: 1; padding: 6px; border: 1px solid #ddd; border-radius: 3px; } .add-author-btn { margin-left: 10px; } .import-export-area { width: 100%; height: 100px; margin-bottom: 10px; border: 1px solid #ddd; padding: 5px; }`) panel.innerHTML = ` <h2> <span>作者屏蔽面板</span> <span class="close-panel" title="关闭面板">×</span> </h2> <div class="category-filter"> <select id="categoryFilter" class="panel-btn"> <option value="all">所有分类</option> </select> </div> <div class="add-author-form"> <input type="text" id="newAuthorName" class="add-author-input" placeholder="作者名称"> <select id="newAuthorCategory" class="panel-btn"> </select> <button id="addAuthorBtn" class="panel-btn add-author-btn">添加</button> </div> <div class="author-list" id="authorList"></div> <div class="panel-actions"> <div> <button id="selectAllBtn" class="panel-btn">全选</button> <button id="deselectAllBtn" class="panel-btn">取消</button> </div> <div> <button id="deleteSelectedBtn" class="panel-btn danger">删除</button> </div> </div> <div class="panel-actions"> <div> <button id="exportBtn" class="panel-btn">导出数据</button> <button id="importBtn" class="panel-btn">导入数据</button> </div> </div> <div id="importExportArea" style="display: none"> <textarea class="import-export-area" id="dataTextarea"></textarea> <div class="panel-actions"> <button id="confirmImportBtn" class="panel-btn primary">确认导入</button> <button id="cancelImportBtn" class="panel-btn">取消</button> </div> </div>` document.body.appendChild(panel) return panel } // 渲染作者列表 const renderAuthorList = (data, filter = 'all') => { const authorList = document.getElementById('authorList') authorList.innerHTML = '' const authors = filter === 'all' ? data.authors : data.authors.filter(author => author.category === filter) if (authors.length === 0) { authorList.innerHTML = '<p>没有作者数据</p>' return } authors.forEach(author => { const authorItem = document.createElement('div') authorItem.className = 'author-item' authorItem.innerHTML = ` <input type="checkbox" class="author-checkbox" data-id="${author.id}" ${author.selected ? 'checked' : ''}> <span class="author-name">${author.name}</span> <span class="category-tag">${author.category}</span> ` authorList.appendChild(authorItem) }) // 添加点击事件 document.querySelectorAll('.author-checkbox').forEach(checkbox => { checkbox.addEventListener('change', function () { const id = parseInt(this.getAttribute('data-id')) data.authors = data.authors.map(author => { if (author.id === id) { author.selected = this.checked } return author }) saveData(data) }) }) } // 渲染分类选择器 const renderCategorySelectors = (data) => { const categoryFilter = document.getElementById('categoryFilter') const newAuthorCategory = document.getElementById('newAuthorCategory') // 清空现有选项 categoryFilter.innerHTML = '<option value="all">所有分类</option>' newAuthorCategory.innerHTML = '' // 添加分类选项 data.categories.forEach(category => { categoryFilter.innerHTML += `<option value="${category}">${category}</option>` newAuthorCategory.innerHTML += `<option value="${category}">${category}</option>` }) } // 主函数 const main = () => { let data = initData() addButton(data) const toggleBtn = createControlButton() const panel = createPanel() renderCategorySelectors(data) renderAuthorList(data) // 切换面板显示/隐藏 const togglePanel = () => { if (panel.style.display === 'none') { panel.style.display = 'block' toggleBtn.innerHTML = '关闭<br>面板' // 刷新数据 data = initData() renderCategorySelectors(data) renderAuthorList(data, document.getElementById('categoryFilter').value) } else { panel.style.display = 'none' toggleBtn.innerHTML = '打开<br>面板' } } // 控制按钮点击事件 toggleBtn.addEventListener('click', togglePanel) // 关闭按钮点击事件 panel.querySelector('.close-panel').addEventListener('click', function () { panel.style.display = 'none' toggleBtn.innerHTML = '打开<br>面板' }) // 分类筛选事件 document.getElementById('categoryFilter').addEventListener('change', function () { renderAuthorList(data, this.value) }) // 添加作者事件 document.getElementById('addAuthorBtn').addEventListener('click', function () { const nameInput = document.getElementById('newAuthorName') const categorySelect = document.getElementById('newAuthorCategory') const name = nameInput.value.trim() if (name) { // 检查是否已存在 const exists = data.authors.some(author => author.name === name) if (exists) { alert('该作者已存在!') return } // 获取最大ID const maxId = data.authors.reduce((max, author) => Math.max(max, author.id), 0) // 添加新作者 data.authors.push({ id: maxId + 1, name: name, category: categorySelect.value, selected: false }) saveData(data) renderAuthorList(data, document.getElementById('categoryFilter').value) nameInput.value = '' } }) // 全选事件 document.getElementById('selectAllBtn').addEventListener('click', function () { const filter = document.getElementById('categoryFilter').value const authorsToUpdate = filter === 'all' ? data.authors : data.authors.filter(author => author.category === filter) data.authors = data.authors.map(author => { if (authorsToUpdate.some(a => a.id === author.id)) { author.selected = true } return author }) saveData(data) renderAuthorList(data, filter) }) // 取消全选事件 document.getElementById('deselectAllBtn').addEventListener('click', function () { const filter = document.getElementById('categoryFilter').value const authorsToUpdate = filter === 'all' ? data.authors : data.authors.filter(author => author.category === filter) data.authors = data.authors.map(author => { if (authorsToUpdate.some(a => a.id === author.id)) { author.selected = false } return author }) saveData(data) renderAuthorList(data, filter) }) // 删除选中事件 document.getElementById('deleteSelectedBtn').addEventListener('click', function () { if (confirm('确定要删除选中的作者吗?')) { data.authors = data.authors.filter(author => !author.selected) saveData(data) renderAuthorList(data, document.getElementById('categoryFilter').value) } }) // 导出数据事件 document.getElementById('exportBtn').addEventListener('click', function () { const importExportArea = document.getElementById('importExportArea') const dataTextarea = document.getElementById('dataTextarea') dataTextarea.value = JSON.stringify(data, null, 2) importExportArea.style.display = 'block' }) // 导入数据事件 document.getElementById('importBtn').addEventListener('click', function () { const importExportArea = document.getElementById('importExportArea') const dataTextarea = document.getElementById('dataTextarea') dataTextarea.value = '' importExportArea.style.display = 'block' }) // 确认导入事件 document.getElementById('confirmImportBtn').addEventListener('click', function () { const dataTextarea = document.getElementById('dataTextarea') try { const newData = JSON.parse(dataTextarea.value) if (newData.categories && newData.authors) { data = newData saveData(data) renderCategorySelectors(data) renderAuthorList(data, document.getElementById('categoryFilter').value) document.getElementById('importExportArea').style.display = 'none' } else { alert('数据格式不正确!') } } catch (e) { alert('解析JSON失败: ' + e.message) } }) // 取消导入/导出事件 document.getElementById('cancelImportBtn').addEventListener('click', function () { document.getElementById('importExportArea').style.display = 'none' }) // 添加拖拽功能 let isDragging = false let offsetX, offsetY panel.querySelector('h2').addEventListener('mousedown', function (e) { if (e.target.className !== 'close-panel') { isDragging = true offsetX = e.clientX - panel.getBoundingClientRect().left offsetY = e.clientY - panel.getBoundingClientRect().top panel.style.cursor = 'grabbing' } }) document.addEventListener('mousemove', function (e) { if (isDragging) { panel.style.left = (e.clientX - offsetX) + 'px' panel.style.top = (e.clientY - offsetY) + 'px' } }) document.addEventListener('mouseup', function () { isDragging = false panel.style.cursor = '' }) } // 加载相关按钮 const addButton = (data) => { // 获取最大ID const maxId = data.authors.reduce((max, author) => Math.max(max, author.id), 0) // 判断是否文章内页 if (document.querySelector('body.single')) { // 加入黑名单 const blockAuthor = () => { const author = document.querySelector('.post-meta span:nth-child(1) a') if (!data.authors.some(i => i.name == author.innerText)) { data.authors.push({ id: maxId + 1, name: author.innerText, category: '默认', selected: false }) } const [blockAuthor, whiteAuthor] = document.querySelectorAll('#blockAuthor, #whiteAuthor') blockAuthor.style.display = 'none' whiteAuthor.style.display = '' saveData(data) renderAuthorList(data, document.getElementById('categoryFilter').value) alert(`已屏蔽作者 ${author.innerText} 的文章, 刷新页面后生效`) } // 移出黑名单 const whiteAuthor = () => { const author = document.querySelector('.post-meta span:nth-child(1) a') data.authors = data.authors.filter(i => i.name != author.innerText) saveData(data) renderAuthorList(data, document.getElementById('categoryFilter').value) const [blockAuthor, whiteAuthor] = document.querySelectorAll('#blockAuthor, #whiteAuthor') blockAuthor.style.display = '' whiteAuthor.style.display = 'none' alert(`已解除对于作者 ${author.innerText} 文章的屏蔽`) } const name = document.querySelector('#post-header .post-meta span:nth-child(1) a') const newListItem = document.createElement('li') const newButton1 = document.createElement('span') newButton1.onclick = blockAuthor newButton1.textContent = '屏蔽他的文章' newButton1.id = 'blockAuthor' newButton1.classList.add('badge') newButton1.style.display = data.authors.some(i => i.name == name.innerText) ? 'none' : '' const newButton2 = document.createElement('span') newButton2.id = 'whiteAuthor' newButton2.classList.add('badge') newButton2.onclick = whiteAuthor newButton2.textContent = '取消屏蔽他的文章' newButton2.style.display = data.authors.some(i => i.name == name.innerText) ? '' : 'none' newListItem.appendChild(newButton1) newListItem.appendChild(newButton2) const socialList = document.querySelector('.author-social') socialList.appendChild(newListItem) // 美化按钮 const styleElement = document.createElement('style') styleElement.innerHTML = ` .author-social .badge { border-radius: 0; line-height: 24px; background-color: #fe9a4b; } .author-social .badge:hover { background-color: #FF7000; } .badge.block { font-size: 11px; }` document.head.appendChild(styleElement) } // 判断是否分类页或标签 if (document.querySelector('body.category') || document.querySelector('body.tag')) { // 文章列表 const authors = document.querySelectorAll('.post-meta span:nth-child(1) a') const posts = document.querySelectorAll('.posts-ul li') authors.forEach((author, index) => { if (data.authors.some(i => i.name == author.innerText)) posts[index].remove() }) } // 判断是否用户中心 if (document.querySelector('body.author')) { if (data.authors.some(i => i.name == document.querySelector('.user-avatar img').alt)) document.querySelector('.widget-content').remove() } // 判断是否含有网站公告 if (document.querySelectorAll('.widget-box.widget.category-posts')) { // 网站公告 const categoryPosts = document.querySelectorAll('.widget-box.widget.category-posts li') categoryPosts.forEach((item, i) => { if (item.childNodes[1].childNodes[1]?.dataset.author && data.authors.some(i => i.name == item.childNodes[1].childNodes[1]?.dataset.author)) item.remove() }) } //判断是否首页 if (document.querySelector('body.home')) { // 最新文章 || 点击排行 || 最新资讯 const recentPosts = document.querySelectorAll('.home-recent li') recentPosts.forEach((Item, i) => { if (Item.childNodes[2]?.dataset?.author && data.authors.some(i => i.name == Item.childNodes[2].dataset.author)) Item.remove() }) // 图包分享 || Cosplay写真 const picBoxPosts = document.querySelectorAll('.pic-box li') picBoxPosts.forEach((Item, i) => { if (Item.childNodes[1]?.dataset?.author && data.authors.some(i => i.name == Item.childNodes[1].dataset.author)) Item.remove() }) // ACG资源聚合 const threePosts = document.querySelectorAll('.three-row li') threePosts.forEach((Item, i) => { if (Item.childNodes[1].childNodes[1]?.dataset?.author && data.authors.some(i => i.name == Item.childNodes[1].childNodes[1].dataset.author)) Item.remove() }) // 音乐分享 || 游戏分享 || 娱乐生活 || 工具&技巧 const columnPosts = document.querySelectorAll('.column2 li') columnPosts.forEach((Item, i) => { if (Item.childNodes[1].childNodes[1] && Item.childNodes[1].childNodes[1]?.dataset?.author && data.authors.some(i => i.name == Item.childNodes[1].childNodes[1].dataset.author)) Item.remove() if (Item.childNodes[3] && Item.childNodes[3]?.dataset.author && data.authors.some(i => i.name == Item.childNodes[3].dataset.author)) Item.remove() }) } //判断当前页面是否含有评论模块 if (document.querySelector('.comment-box')) { const commentList = document.querySelectorAll('.commentlist .comment') const commentIdList = document.querySelectorAll('.conment_id') // 加入黑名单 const blockCommentAuthor = (vl) => { if (!data.authors.some(i => i.name == vl.target.name)) { data.authors.push({ id: maxId + 1, name: vl.target.name, category: '默认', selected: false }) } const whiteClass = vl.target.id.replace('block', 'white') const whiteAuthor = document.querySelector(`#${whiteClass}`) vl.target.style.display = 'none' whiteAuthor.style.display = '' saveData(data) renderAuthorList(data, document.getElementById('categoryFilter').value) alert(`已屏蔽 ${vl.target.name} 的评论, 刷新页面后生效`) } // 移出黑名单 const whiteCommentAuthor = (vl) => { const name = document.querySelector('.comment-author .conment_id a:nth-child(1)').innerText data.authors = data.authors.filter(i => i.name != name) saveData(data) renderAuthorList(data, document.getElementById('categoryFilter').value) const blockClass = vl.target.id.replace('white', 'block') const blockAuthor = document.querySelector(`#${blockClass}`) blockAuthor.style.display = '' vl.target.style.display = 'none' alert(`已解除对于 ${vl.target.name} 评论的屏蔽`) } // 如果有评论的话 if (commentIdList.length > 0) { commentIdList.forEach((author, index) => { const commentButton1 = document.createElement('span') commentButton1.onclick = blockCommentAuthor commentButton1.textContent = '屏蔽他的评论' commentButton1.id = `blockCommentAuthor-${index}` commentButton1.classList = 'badge block' commentButton1.style.display = data.authors.some(i => i.name == author.childNodes[0].innerText) ? 'none' : '' commentButton1.name = author.childNodes[0].innerText const commentButton2 = document.createElement('span') commentButton2.id = `whiteCommentAuthor-${index}` commentButton2.classList = 'badge block' commentButton2.onclick = whiteCommentAuthor commentButton2.textContent = '取消屏蔽他的评论' commentButton2.style.display = data.authors.some(i => i.name == author.childNodes[0].innerText) ? '' : 'none' commentButton2.name = author.childNodes[0].innerText author.appendChild(commentButton1) author.appendChild(commentButton2) commentList[index].title = author.childNodes[0].innerText // 隐藏评论 if (data.authors.some(i => i.name == author.childNodes[0].innerText)) commentList[index].remove() }) } } } // 启动脚本 main() })()