您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
使用模态框实现的版面拦截器
// ==UserScript== // @name RedirectFromCertainCC98Board // @namespace http://tampermonkey.net/ // @version 2025-02-25 // @description 使用模态框实现的版面拦截器 // @author Monci // @match *://www.cc98.org/* // @match *://www-cc98-org-s.webvpn.zju.edu.cn:8001/* // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @license MIT // ==/UserScript== // 关于创建窗口的方案和脚本头部的参数借鉴了yacu - Yet another CC98 userscript(https://update.greasyfork.org/scripts/438399/yacu%20-%20Yet%20another%20CC98%20userscript.user.js) // 安装后启用,在cc98论坛内部所有页面右侧顶端生成一个透明蓝色按钮,点击按钮弹出对话框指定需要拦截的版面。打开相应版面的帖子时,将自动重定向到cc98论坛的主页(使用webvpn访问情况下也生效) (function () { 'use strict'; const FIXED_BOARD_LIST = ["感性空间", "心灵之约", "郁闷小屋", ]; let boardConditions = JSON.parse(GM_getValue('boardConditions', '[]')); let isModalOpen = false; // 用于跟踪模态框是否已经打开 // 添加全局样式(仅修改按钮部分) GM_addStyle(` .blocker-modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.2); z-index: 10000; min-width: 300px; } .modal-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 9999; } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .modal-close { cursor: pointer; font-size: 24px; } .board-list { display: flex; flex-wrap: wrap; gap: 10px; } .board-item { flex: 1 0 30%; /* 每个版面占用30%的宽度,确保每行最多显示3个 */ margin: 8px 0; display: flex; align-items: center; } /* 处理不足三个版面时,最后一个项居中显示 */ .board-item:nth-child(3n+1) { margin-left: 0; } .board-item:nth-child(3n) { margin-right: 0; } .save-button { margin-top: 15px; padding: 8px 20px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } /* 新增按钮样式 */ .floating-btn { background: #007bff !important; color: white !important; border: none !important; border-radius: 4px !important; padding: 8px 16px !important; opacity: 0.2 !important; transition: opacity 0.3s ease !important; cursor: pointer !important; box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important; } .floating-btn:hover { opacity: 1 !important; } .board-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 15px; } .board-item { display: flex; align-items: center; white-space: nowrap; gap: 8px; margin: 0 !important; } `); // 创建控制按钮(修改后) function createControlButton() { const btn = document.createElement('button'); btn.className = 'floating-btn'; // 应用新样式类 btn.textContent = '拦截设置'; // 位置设置保持不变 btn.style.position = 'fixed'; btn.style.top = '10px'; btn.style.right = '10px'; btn.style.zIndex = '10000'; btn.addEventListener('click', showModal); document.body.appendChild(btn); } // 显示模态框 function showModal() { // 如果模态框已经打开,直接返回 if (isModalOpen) return; isModalOpen = true; // 标记模态框为已打开 const mask = document.createElement('div'); mask.className = 'modal-mask'; const modal = document.createElement('div'); modal.className = 'blocker-modal'; // 弹窗内容 modal.innerHTML = ` <div class="modal-header"> <h3>选择要拦截的版面</h3> <div class="modal-close">×</div> </div> <div class="board-list"> ${FIXED_BOARD_LIST.map(name => ` <label class="board-item"> <input type="checkbox" ${boardConditions.includes(name) ? 'checked' : ''}> ${name} </label> `).join('')} </div> <button class="save-button">保存设置</button> `; // 关闭事件 const closeBtn = modal.querySelector('.modal-close'); closeBtn.addEventListener('click', () => { mask.remove(); isModalOpen = false; // 标记模态框已关闭 }); mask.addEventListener('click', (e) => { if (e.target === mask) { mask.remove(); isModalOpen = false; // 标记模态框已关闭 } }); // 保存事件 const saveBtn = modal.querySelector('.save-button'); saveBtn.addEventListener('click', () => { const checked = Array.from(modal.querySelectorAll('input:checked')) .map(input => input.parentNode.textContent.trim()); boardConditions = checked; GM_setValue('boardConditions', JSON.stringify(checked)); mask.remove(); isModalOpen = false; // 标记模态框已关闭 checkRedirect(); // 立即应用新规则 }); mask.appendChild(modal); document.body.appendChild(mask); } // 确认是否是通过webvpn访问 function getRedirectURL() { // 判断当前是否在VPN域名下 const isVPN = window.location.hostname.includes('webvpn.zju.edu.cn'); return isVPN ? 'http://www-cc98-org-s.webvpn.zju.edu.cn:8001/' : 'https://www.cc98.org/'; } // 检查是否需要重定向 function checkRedirect() { const currentBoard = document.querySelector("#root > div > div.center > div:nth-child(1) > div > div.row > a:nth-child(5)"); // 根据实际页面结构调整选择器 if (currentBoard && boardConditions.includes(currentBoard.textContent.trim())) { // window.location.href = 'https://www.cc98.org/'; window.location.href = getRedirectURL(); } } // 初始化 function init() { createControlButton(); checkRedirect(); // 添加DOM变化监听(根据实际需要) new MutationObserver(checkRedirect).observe(document.body, { childList: true, subtree: true }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();