您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
将B站评论区移动到右侧容器
// ==UserScript== // @name 把B站评论区挪到右边,边看视频边看评论 // @namespace http://tampermonkey.net/ // @version 2025.08.01 // @description 将B站评论区移动到右侧容器 // @author FruitJellies // @match https://www.bilibili.com/video/* // @match https://www.bilibili.com/list/* // @icon https://www.bilibili.com/favicon.ico // @grant GM_addStyle // @license MIT // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; const path = window.location.pathname; // 配置对象 const CONFIG = { containerSelector: "#mirror-vdcon > div.right-container", playlistContainerSelector: "#mirror-vdcon > div.playlist-container--right", commentAppSelector: "#commentapp", playlistTargetPositionSelector:"#mirror-vdcon > div.playlist-container--right > div.recommend-list-container", targetPositionSelector: ".recommend-list-v1", observerConfig: { childList: true, subtree: true, attributes: false }, timeoutDuration: 9999999999, // 999……秒超时 styleSettings: { containerWidth: "23%", containerHeight: "110vh", hideScrollbar: true // 默认隐藏滚动条 } }; // 全局变量 let observer = null; let timeoutId = null; let isCommentsMoved = false; let originalPosition = null; let cachedElements = {}; // 缓存DOM元素 function getCachedElement(selector) { if (!cachedElements[selector]) { cachedElements[selector] = document.querySelector(selector); } return cachedElements[selector]; } // 安全DOM操作 function safeDOMOperation(operation) { try { return operation(); } catch (error) { console.error('[BCTR] DOM操作失败:', error); return null; } } // 初始化容器样式 function initContainerStyles() { // 从存储中读取用户配置,若无则使用默认值 const hideScrollbar = GM_getValue('hideScrollbar', CONFIG.styleSettings.hideScrollbar); const commonStyles = ` width: ${CONFIG.styleSettings.containerWidth}; height: ${CONFIG.styleSettings.containerHeight}; overflow-y: scroll !important; ${hideScrollbar ? 'scrollbar-width: none;' : ''} pointer-events: auto !important; `; // 动态生成滚动条隐藏样式 const scrollbarStyle = hideScrollbar ? ` ${CONFIG.playlistContainerSelector}::-webkit-scrollbar, ${CONFIG.containerSelector}::-webkit-scrollbar { display: none; } ` : ''; GM_addStyle(` ${CONFIG.playlistContainerSelector}, ${CONFIG.containerSelector} { ${commonStyles} } ${scrollbarStyle} body { overflow: auto !important; } `); } // 处理评论区移动 function handleCommentsMove() { return safeDOMOperation(() => { const commentApp = getCachedElement(CONFIG.commentAppSelector); const shadowContent = commentApp?.querySelector('bili-comments')?.shadowRoot?.querySelector('#contents'); const targetPositionSelector = path.startsWith('/list/') ? CONFIG.playlistTargetPositionSelector : CONFIG.targetPositionSelector; const targetPosition = getCachedElement(targetPositionSelector); if (!commentApp || !targetPosition || !shadowContent) { return false; } // 保存原始位置 if (!originalPosition) { originalPosition = commentApp.parentNode; } targetPosition.parentNode.insertBefore(commentApp, targetPosition); console.log('[BCTR] 评论区移动成功'); isCommentsMoved = true; return true; }); } // 恢复评论区到原始位置 function restoreCommentsPosition() { return safeDOMOperation(() => { const commentApp = getCachedElement(CONFIG.commentAppSelector); if (!commentApp || !originalPosition) { return false; } originalPosition.appendChild(commentApp); console.log('[BCTR] 评论区恢复成功'); isCommentsMoved = false; return true; }); } // 切换评论区位置 function toggleCommentsPosition() { isCommentsMoved ? restoreCommentsPosition() : handleCommentsMove(); } // 创建切换按钮 function createToggleButton() { const titleElement = path.startsWith('/list/') ?getCachedElement("#playlistToolbar > div.video-toolbar-right > div.video-note.video-toolbar-right-item.toolbar-right-note") :getCachedElement("#arc_toolbar_report > div.video-toolbar-right > div.video-note.video-toolbar-right-item.toolbar-right-note"); if (!titleElement) return; const toggleBtn = document.createElement('button'); toggleBtn.className = 'comment-toggle-btn'; toggleBtn.textContent = '⇄'; toggleBtn.title = '切换评论区位置'; toggleBtn.addEventListener('click', toggleCommentsPosition); titleElement.appendChild(toggleBtn); const style = document.createElement('style'); style.textContent = ` .comment-toggle-btn { border-radius: 6px !important; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; margin-left: 12px; background-color: #fb7299; color: white; border: none; cursor: pointer; vertical-align: middle; font-size: 14px; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); position: relative; overflow: hidden; box-sizing: border-box; z-index: 1; } @media (prefers-color-scheme: dark) { .comment-toggle-btn { background-color: #ff85ad; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } `; document.head.appendChild(style); } // 清理资源 function cleanupResources() { if (observer) { observer.disconnect(); observer = null; } if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } cachedElements = {}; console.log('[BCTR] 已释放观察器和定时器'); } // MutationObserver回调 function mutationCallback(mutationsList) { for (const mutation of mutationsList) { if (mutation.type === 'childList' && handleCommentsMove()) { cleanupResources(); createToggleButton(); break; } } } //禁用标题超链接 function disableTitleLink() { const titleLink = document.querySelector("#mirror-vdcon > div.playlist-container--left > div.video-info-container.mac > div.video-info-title > div > h1 > a"); if (titleLink) { titleLink.removeAttribute('href'); titleLink.style.cursor = 'default'; titleLink.style.textDecoration = 'none'; titleLink.style.color = 'inherit'; console.log('[BCTR] 已禁用标题超链接'); } } //脚本设置 function registerSettingsMenu() { GM_registerMenuCommand("⚙️ 脚本设置", function() { const currentValue = GM_getValue('hideScrollbar', CONFIG.styleSettings.hideScrollbar); const newValue = confirm(`当前滚动条设置:${currentValue ? '隐藏' : '显示'}\n\n是否切换?`); if (newValue !== null) { GM_setValue('hideScrollbar', !currentValue); alert('设置已保存!刷新页面后生效'); } }); } // 初始化函数 function init() { if (path.startsWith('/list/')) disableTitleLink(); // 更精确地选择观察目标 const observeTarget = document.body || document.documentElement; observer = new MutationObserver(mutationCallback); observer.observe(observeTarget, CONFIG.observerConfig); timeoutId = setTimeout(() => { console.warn('[BCTR] 操作超时,终止检测'); cleanupResources(); }, CONFIG.timeoutDuration); registerSettingsMenu(); initContainerStyles(); console.log('[BCTR] 脚本初始化完成'); } // 启动脚本 try { init(); } catch (error) { console.error('[BCTR] 脚本初始化失败:', error); cleanupResources(); } })();