// ==UserScript== // @name My-抖音优化 // @namespace douyin-live-optimized-ai.local // @version v2026.06.08.3 // @description 这是一个使用AI写的抖音网页版优化脚本,仅供本人使用,不保证功能正常,有需要可以自己修改。 // @author 云上夜未央 // @license GPL-3.0-only // @original-author WhiteSevs // @original-license GPL-3.0-only // @original-script https://scriptcat.org/zh-CN/script-show-page/2534 // @match https://live.douyin.com/* // @match https://www.douyin.com/follow/live/* // @match https://www.douyin.com/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @run-at document-start // @noframes // ==/UserScript== (function () { 'use strict'; // ================================================================ // 一、版本与存储 // ================================================================ const VERSION = 'v2026.06.08.3'; const STORE_KEY = 'dy_opt'; const LIVE_RE = /live\.douyin\.com|douyin\.com\/follow\/live\//; const HIDDEN_TAB_IDS = new Set(['video']); let store = {}; const DEBUG = false; function log(...args) { if (DEBUG) console.log('[GB]', ...args); } function loadStore() { try { const raw = GM_getValue(STORE_KEY, null); if (raw && typeof raw === 'object') { store = raw; } } catch (e) { /* 忽略 */ } } function saveStore() { try { GM_setValue(STORE_KEY, store); } catch (e) { /* 忽略 */ } } function getVal(k, d) { return Object.prototype.hasOwnProperty.call(store, k) ? store[k] : d; } function setVal(k, v) { store[k] = v; saveStore(); } loadStore(); // ================================================================ // 二、主题检测 // ================================================================ let THEME = 'dark'; function detectTheme() { const override = getVal('ui_theme', 'auto'); if (override === 'dark') { THEME = 'dark'; applyTheme(); return; } if (override === 'light') { THEME = 'light'; applyTheme(); return; } // 自动模式:优先跟随抖音自身深浅色标识,再回退到页面背景/系统主题 THEME = detectDouyinTheme(); applyTheme(); } function detectDouyinTheme() { try { const roots = [document.documentElement, document.body].filter(Boolean); for (const el of roots) { const attrs = [ el.getAttribute('data-theme'), el.getAttribute('data-color-mode'), el.getAttribute('color-mode'), el.getAttribute('arco-theme'), el.className ].join(' ').toLowerCase(); if (/dark|black|night|深色|暗色/.test(attrs)) return 'dark'; if (/light|white|day|浅色|亮色/.test(attrs)) return 'light'; } const themed = document.querySelector('[data-theme="dark"], [data-theme="light"], [arco-theme="dark"], [arco-theme="light"], .dark, .light'); if (themed && themed.id !== 'gb-panel' && !themed.closest('#gb-panel')) { const mark = [themed.getAttribute('data-theme'), themed.getAttribute('arco-theme'), themed.className].join(' ').toLowerCase(); if (/dark|black|night/.test(mark)) return 'dark'; if (/light|white|day/.test(mark)) return 'light'; } const bgCandidates = [ getComputedStyle(document.documentElement).backgroundColor, document.body ? getComputedStyle(document.body).backgroundColor : '', getComputedStyle(document.documentElement).getPropertyValue('--background-color'), getComputedStyle(document.documentElement).getPropertyValue('--bg-color') ]; for (const bg of bgCandidates) { const m = bg && bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); if (m) { const brightness = (parseInt(m[1]) * 299 + parseInt(m[2]) * 587 + parseInt(m[3]) * 114) / 1000; return brightness > 128 ? 'light' : 'dark'; } } if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark'; } catch (e) { /* 忽略 */ } return 'light'; } function applyTheme() { document.documentElement.setAttribute('data-gb-theme', THEME); if (panel) panel.setAttribute('data-theme', THEME); document.querySelectorAll('.gb-dd-menu').forEach(menu => menu.setAttribute('data-theme', THEME)); } let themeObserver = null; function observeDouyinTheme() { if (themeObserver || !window.MutationObserver) return; themeObserver = new MutationObserver(() => { if (getVal('ui_theme', 'auto') === 'auto') detectTheme(); }); [document.documentElement, document.body].filter(Boolean).forEach(el => { themeObserver.observe(el, { attributes: true, attributeFilter: ['class', 'style', 'data-theme', 'data-color-mode', 'color-mode', 'arco-theme'] }); }); } // ================================================================ // 三、模块定义 // ================================================================ const TABS = [ { id: 'general', label: '通用', icon: '⚙️', modules: [ { id: 'generalAll', title: '通用设置', defaultOpen: true, type: 'mixed', switchItems: [ { key: 'block_login_dialog', name: '屏蔽登录弹窗', desc: '自动关闭登录弹窗和登录提示', def: false }, { key: 'block_idle_pause', name: '屏蔽暂停弹窗', desc: '自动跳过长时间无操作暂停,支持后台听声音', def: false }, ], inlineDropdowns: [ { key: 'ui_theme', title: '主题模式', def: 'auto', options: [ { value: 'auto', label: '自动切换' }, { value: 'dark', label: '深色模式' }, { value: 'light', label: '浅色模式' } ] } ] } ] }, { id: 'live', label: '直播', icon: '📺', modules: [ { id: 'baseSettings', title: '基础设置', defaultOpen: true, type: 'mixed', switchItems: [ { key: 'auto_mute', name: '自动静音', desc: '开启后自动处理静音状态。刷新后自动静音是浏览器限制,解决方法:地址栏🔒 → 网站设置 → 声音 → 允许,之后刷新就有声了。', def: false }, ], inlineDropdowns: [ { key: 'live_fullscreen', title: '自动全屏', def: 'web', options: [ { value: 'none', label: '不启用' }, { value: 'web', label: '网页全屏 (Y键)' }, { value: 'native', label: '真全屏 (H键)' } ] }, { key: 'live_quality', title: '清晰度', def: 'auto', options: [ { value: 'auto', label: '自动(最高)' }, { value: 'origin', label: '原画' }, { value: 'uhd', label: '蓝光' }, { value: 'hd', label: '超清' }, { value: 'sd', label: '高清' }, { value: 'ld', label: '标清' } ] } ] }, { id: 'giftBar', title: '礼物屏蔽', defaultOpen: true, type: 'switch', items: [ { key: 'gift_block', name: '屏蔽礼物栏', desc: '屏蔽左侧礼物列表和赠送按钮', def: false }, { key: 'block_gift_column', name: '屏蔽底部礼物栏', desc: '屏蔽直播底部的礼物选择区域', def: false }, { key: 'gift_effect_block', name: '屏蔽礼物特效', desc: '屏蔽全屏礼物动画特效', def: false }, { key: 'diamond_block', name: '屏蔽钻石充值', desc: '屏蔽右侧钻石数量和充值入口', def: false }, { key: 'link_block', name: '屏蔽连麦PK', desc: '屏蔽连线/连麦/PK按钮', def: false }, { key: 'block_yellow_car', name: '屏蔽黄色小黄车', desc: '屏蔽直播间商品购物车', def: false }, { key: 'block_lucky_bag', name: '屏蔽福袋', desc: '屏蔽直播福袋活动', def: false }, { key: 'block_game_widget', name: '屏蔽游戏控件', desc: '屏蔽直播间游戏入口挂件', def: false }, ] }, { id: 'liveMsg', title: '消息过滤', defaultOpen: false, type: 'switch', items: [ { key: 'block_live_danmaku', name: '屏蔽弹幕', desc: '隐藏直播弹幕层', def: false }, { key: 'block_live_emoji', name: '屏蔽表情图片', desc: '屏蔽直播聊天中的表情图片', def: false }, { key: 'block_gift_float', name: '屏蔽礼物飘屏', desc: '屏蔽弹幕层中的礼物动画飘屏效果', def: false }, { key: 'block_gift_notice', name: '屏蔽左下角礼物提示', desc: '屏蔽左下角显示的送礼小弹窗', def: false }, { key: 'block_lucky_float', name: '屏蔽福袋口令飘屏', desc: '屏蔽弹幕层中的福袋口令飘屏提示', def: false }, { key: 'block_live_room_msg', name: '屏蔽系统通知', desc: '屏蔽"xxx为主播加分"等系统信息', def: false }, { key: 'block_user_level_icon', name: '屏蔽等级图标', desc: '屏蔽聊天室中的用户等级图标', def: false }, { key: 'block_vip_icon', name: '屏蔽VIP标识', desc: '屏蔽聊天室中的VIP图标', def: false }, { key: 'block_fans_icon', name: '屏蔽粉丝徽章', desc: '屏蔽聊天室中的粉丝牌图标', def: false }, ] }, { id: 'livePlayer', title: '播放器组件', defaultOpen: false, type: 'switch', items: [ { key: 'block_chatroom', name: '屏蔽聊天室', desc: '隐藏直播聊天室', def: false }, { key: 'block_top_bar', name: '屏蔽主播信息', desc: '隐藏直播顶部主播信息栏', def: false }, { key: 'block_live_player_controls', name: '屏蔽播放控件', desc: '屏蔽直播播放器底部控件', def: false }, { key: 'block_live_play_btn', name: '屏蔽播放按钮', desc: '屏蔽播放/暂停按钮', def: false }, { key: 'block_live_refresh_btn', name: '屏蔽刷新按钮', desc: '屏蔽刷新按钮', def: false }, { key: 'block_live_quality_btn', name: '屏蔽清晰度按钮', desc: '屏蔽清晰度切换按钮', def: false }, { key: 'block_live_volume_btn', name: '屏蔽音量按钮', desc: '屏蔽音量控制按钮', def: false }, { key: 'block_live_fullscreen_btn', name: '屏蔽全屏按钮', desc: '屏蔽全屏切换按钮', def: false }, { key: 'block_live_danmaku_switch', name: '屏蔽弹幕设置', desc: '屏蔽弹幕设置按钮', def: false }, { key: 'block_live_gift_setting', name: '屏蔽礼物设置', desc: '屏蔽礼物设置按钮', def: false }, ] }, ] }, { id: 'video', label: '视频', icon: '📹', modules: [ { id: 'videoDanmaku', title: '弹幕屏蔽', defaultOpen: true, type: 'switch', items: [ { key: 'block_video_danmaku', name: '屏蔽视频弹幕', desc: '隐藏视频播放器弹幕', def: false } ] }, { id: 'videoBlock', title: '视频屏蔽', defaultOpen: false, type: 'switch', items: [ { key: 'block_video_ads', name: '屏蔽视频广告', desc: '屏蔽视频中的广告内容', def: false }, { key: 'block_related_video', name: '屏蔽相关视频', desc: '屏蔽右侧相关视频推荐', def: false }, { key: 'block_video_right_toolbar', name: '屏蔽右侧工具栏', desc: '屏蔽视频右侧工具栏', def: false }, { key: 'block_video_title', name: '屏蔽视频标题', desc: '屏蔽视频标题信息区域', def: false }, { key: 'block_video_progress', name: '屏蔽进度条', desc: '屏蔽视频进度条', def: false }, { key: 'block_video_share_btn', name: '屏蔽分享按钮', desc: '屏蔽视频分享按钮', def: false }, { key: 'block_video_like_btn', name: '屏蔽点赞按钮', desc: '屏蔽视频点赞按钮', def: false }, { key: 'block_video_collect_btn', name: '屏蔽收藏按钮', desc: '屏蔽视频收藏按钮', def: false }, { key: 'block_comment_btn', name: '屏蔽评论按钮', desc: '隐藏视频评论按钮', def: false }, ] }, { id: 'bgColor', title: '背景色', defaultOpen: false, type: 'color', key: 'video_bg_color', def: '#000000', desc: '自定义视频播放区域和评论区背景色' } ] }, { id: 'about', label: '关于', icon: '👤', modules: [ { id: 'aboutInfo', title: '关于本脚本', defaultOpen: true, type: 'info' } ] } ]; // ================================================================ // 四、资源管理(定时器统一管控) // ================================================================ const activeTimers = new Set(); function managedSetTimeout(fn, ms) { const id = setTimeout(() => { activeTimers.delete(id); fn(); }, ms); activeTimers.add(id); return id; } function managedSetInterval(fn, ms, maxCount) { let count = 0; const id = setInterval(() => { count++; if (count >= maxCount) { clearManagedInterval(id); return; } fn(id, count); }, ms); activeTimers.add(id); return id; } function clearManagedInterval(id) { clearInterval(id); activeTimers.delete(id); } function clearAllTimers() { activeTimers.forEach(id => { clearTimeout(id); clearInterval(id); }); activeTimers.clear(); } // ================================================================ // 五、工具函数 // ================================================================ let blockStyleEl = null; let guardOn = false; const roomFlags = {}; const qualityCache = {}; const MAX_ROOM_CACHE = 50; const KEY_MAP = { a: 65, b: 66, c: 67, d: 68, e: 69, f: 70, g: 71, h: 72, i: 73, j: 74, k: 75, l: 76, m: 77, n: 78, o: 79, p: 80, q: 81, r: 82, s: 83, t: 84, u: 85, v: 86, w: 87, x: 88, y: 89, z: 90 }; function isVideoEl(el) { return el && el.tagName === 'VIDEO'; } function hideEl(el) { if (!el || isVideoEl(el) || el.getAttribute('data-gb') === '1') return; el.setAttribute('data-gb', '1'); el.style.setProperty('display', 'none', 'important'); el.style.setProperty('pointer-events', 'none', 'important'); } function showEl(el) { if (!el || el.getAttribute('data-gb') !== '1') return; el.removeAttribute('data-gb'); el.style.removeProperty('display'); el.style.removeProperty('pointer-events'); } function ensureBlockStyleEl() { if (!blockStyleEl) { try { blockStyleEl = GM_addStyle(''); } catch (e) { blockStyleEl = document.createElement('style'); blockStyleEl.id = 'gb-block-css'; (document.head || document.documentElement).appendChild(blockStyleEl); } } return blockStyleEl; } let blockCSSContent = ''; function appendBlockCSS(css) { if (blockCSSContent.includes(css)) return; blockCSSContent += css + '\n'; ensureBlockStyleEl().textContent = blockCSSContent; } function clearBlockCSS() { blockCSSContent = ''; if (blockStyleEl) blockStyleEl.textContent = ''; } function clearAll() { document.querySelectorAll('[data-gb="1"]').forEach(showEl); clearBlockCSS(); const root = findGiftRoot(); if (root) { ['background-color', 'background', 'box-shadow', 'border', 'padding', 'margin', 'min-height'] .forEach(p => root.style.removeProperty(p)); } document.removeEventListener('click', clickGuard, true); guardOn = false; } function installGuard() { if (guardOn) return; document.addEventListener('click', clickGuard, true); guardOn = true; } function clickGuard(e) { let t = e.target; while (t) { if (t.id === 'gb-panel') return; t = t.parentElement; } let el = e.target; for (let i = 0; i < 8 && el; i++) { const d2e = el.getAttribute ? el.getAttribute('data-e2e') : ''; if (d2e === 'gift-btn' || d2e === 'gifts-container' || d2e === 'gifts-switch') { if (getVal('gift_block', false)) { e.preventDefault(); e.stopImmediatePropagation(); return; } } if (d2e === 'recharge-btn') { if (getVal('diamond_block', false)) { e.preventDefault(); e.stopImmediatePropagation(); return; } } const cls = typeof el.className === 'string' ? el.className : ''; if (cls.indexOf('gift_item_gift_bar') !== -1) { if (getVal('gift_block', false)) { e.preventDefault(); e.stopImmediatePropagation(); return; } } if (getVal('link_block', false)) { const txt = (el.textContent || '').trim().slice(0, 20); if (/连线|连麦|PK/i.test(txt)) { const rect = el.getBoundingClientRect(); if (rect.height > 0 && rect.height < 80) { e.preventDefault(); e.stopImmediatePropagation(); return; } } } el = el.parentElement; } } function simulateKey(key) { const ae = document.activeElement; if (ae && (ae.tagName === 'INPUT' || ae.tagName === 'TEXTAREA' || ae.isContentEditable)) { ae.blur(); } const kc = KEY_MAP[key.toLowerCase()] || key.toUpperCase().charCodeAt(0); const opts = { key, code: 'Key' + key.toUpperCase(), keyCode: kc, which: kc, bubbles: true, cancelable: true }; // 只在 document 上派发,避免多次触发 document.dispatchEvent(new KeyboardEvent('keydown', opts)); document.dispatchEvent(new KeyboardEvent('keyup', opts)); } function isLivePage() { return LIVE_RE.test(location.href) && !!document.querySelector('video'); } function getRoomId() { let m = location.href.match(/\/live\/(\d+)/); if (m) return m[1]; m = location.href.match(/live\.douyin\.com\/(\d+)/); if (m) return m[1]; return location.pathname; } function findGiftRoot() { const c = document.querySelector('[data-e2e="gifts-container"]'); if (!c) return null; const area = c.parentElement; return area ? area.parentElement : null; } // ================================================================ // 六、功能实现 // ================================================================ function scanAndBlock() { if (getVal('gift_block', false)) { const c = document.querySelector('[data-e2e="gifts-container"]'); if (c && c.parentElement) hideEl(c.parentElement); const sw = document.querySelector('[data-e2e="gifts-switch"]'); if (sw) hideEl(sw); document.querySelectorAll('.gift_item_gift_bar').forEach(hideEl); document.querySelectorAll('[data-e2e="gift-btn"]').forEach(hideEl); const root = findGiftRoot(); if (root) { for (const ch of root.children) { if (ch.querySelector && ch.querySelector('path[fill="#13C15A"]')) hideEl(ch); } } } if (getVal('gift_effect_block', false)) applyGiftEffectBlock(); if (getVal('diamond_block', false)) { const rb = document.querySelector('[data-e2e="recharge-btn"]'); if (rb && rb.parentElement) hideEl(rb.parentElement); const rc = document.querySelector('.giftRechargeContaner'); if (rc && rc.parentElement) hideEl(rc.parentElement); } if (getVal('link_block', false)) applyLinkBlock(); applyTooltipBlock(); reconcileRoot(); } function applyGiftBlock() { appendBlockCSS( 'div:has(> [data-e2e="gifts-container"]){display:none!important}\n' + '[data-e2e="gifts-container"],[data-e2e="gifts-switch"],.gift_item_gift_bar,[data-e2e="gift-btn"]{display:none!important;pointer-events:none!important}' ); installGuard(); } function applyDiamondBlock() { appendBlockCSS( 'div:has(> [data-e2e="recharge-btn"]){display:none!important}\n' + '[data-e2e="recharge-btn"]{display:none!important;pointer-events:none!important}\n' + 'div:has(> .giftRechargeContaner){display:none!important}\n' + '.giftRechargeContaner{display:none!important}' ); installGuard(); } function reconcileRoot() { const root = findGiftRoot(); if (!root || isVideoEl(root)) return; const giftOn = getVal('gift_block', false); const diamondOn = getVal('diamond_block', false); if (giftOn && diamondOn) { hideEl(root); } else if (giftOn || diamondOn) { root.style.setProperty('background-color', 'transparent', 'important'); root.style.setProperty('background', 'transparent', 'important'); root.style.setProperty('box-shadow', 'none', 'important'); root.style.setProperty('border', 'none', 'important'); } } function applyLinkBlock() { const kw = /申请连线|连线|连麦|申请PK|断开连线|断开连麦/; document.querySelectorAll('.operate-text').forEach(el => { if (kw.test((el.textContent || '').trim())) { const btn = el.closest('button') || el.closest('[role="button"]'); if (btn) hideEl(btn); } }); document.querySelectorAll('img[alt*="连线"], img[alt*="连麦"]').forEach(img => { const btn = img.closest('button') || img.closest('[role="button"]'); if (btn) hideEl(btn); }); document.querySelectorAll('button, [role="button"]').forEach(btn => { const t = (btn.textContent || '').trim().slice(0, 25); if (/^申请连线$|^申请连麦$|^申请PK$|^断开连线$|^断开连麦$/.test(t)) hideEl(btn); }); installGuard(); } function applyTooltipBlock() { document.querySelectorAll('.dylive-tooltip').forEach(hideEl); } // ================================================================ // 新增屏蔽功能 // ================================================================ function applyBlockLoginDialog() { if (!getVal('block_login_dialog', false)) return; appendBlockCSS( 'div[id^="login-full-panel-"]{display:none!important}\n' + '.douyin_login_iframe:has(iframe){display:none!important}\n' + '[id^="related-video-card-login-guide"]{display:none!important}' ); } function applyBlockIdlePause() { if (!getVal('block_idle_pause', false)) return; appendBlockCSS( '.tPjpbR8_{display:none!important}\n' + '.EiGv3P09{display:none!important}\n' + '.C4DUhSTs{display:none!important}\n' + '.KQTNS6Ni{display:none!important}\n' + '.Lp_3msye{display:none!important}\n' + '.elw1KV8O{display:none!important}' ); const autoClick = () => { const btns = document.querySelectorAll('.JL05k7eS'); for (const btn of btns) { if (btn.textContent && btn.textContent.includes('继续播放')) { btn.click(); console.log('[油猴] 自动点击继续播放'); break; } } }; const observer = new MutationObserver(() => { const popup = document.querySelector('.tPjpbR8_'); if (popup) autoClick(); }); observer.observe(document.body, { childList: true, subtree: true }); } function applyBlockVideoAds() { if (!getVal('block_video_ads', false)) return; appendBlockCSS( '[data-e2e="feed-ad"]{display:none!important}\n' + '.video-feed-ad{display:none!important}\n' + '[class*="ad-card"]{display:none!important}' ); } function applyBlockRelatedVideo() { if (!getVal('block_related_video', false)) return; appendBlockCSS('#relatedVideoCard{display:none!important}'); } function applyBlockVideoRightToolbar() { if (!getVal('block_video_right_toolbar', false)) return; appendBlockCSS('.positionBox{display:none!important}'); } function applyBlockVideoTitle() { if (!getVal('block_video_title', false)) return; appendBlockCSS('#video-info-wrap{display:none!important}'); } function applyBlockVideoProgress() { if (!getVal('block_video_progress', false)) return; appendBlockCSS('.xg-bottom-progress{display:none!important}'); } function applyBlockVideoShareBtn() { if (!getVal('block_video_share_btn', false)) return; appendBlockCSS('[data-e2e="feed-share-icon"]{display:none!important}'); } function applyBlockVideoLikeBtn() { if (!getVal('block_video_like_btn', false)) return; appendBlockCSS('[data-e2e="feed-like-icon"]{display:none!important}'); } function applyBlockVideoCollectBtn() { if (!getVal('block_video_collect_btn', false)) return; appendBlockCSS('[data-e2e="feed-collect-icon"]{display:none!important}'); } function applyBlockGiftColumn() { if (!getVal('block_gift_column', false)) return; appendBlockCSS( 'div[data-e2e="living-container"] [id^="living_room_player_container"] > :last-child:has(.gitBarOptimizeEnabled){display:none!important}\n' + 'div[data-e2e="living-container"] >div> div:has(>pace-island >.gitBarOptimizeEnabled){display:none!important}\n' + 'div[data-e2e="living-container"] xg-controls > div:has(div[data-e2e="gifts-container"]):not(:has(video)){display:none!important}\n' + '#BottomLayout:not([data-multi-camera]){display:none!important}\n' + '.douyin-player .douyin-player-controls >div:nth-child(2):has(> .gitBarOptimizeEnabled ){display:none!important}' ); } function applyBlockYellowCar() { if (!getVal('block_yellow_car', false)) return; appendBlockCSS( 'div[id^="living_room_player_container"] .basicPlayer > div:has(div[data-e2e="yellowCart-container"]){display:none!important}\n' + '#EcmoCardLayout{display:none!important}' ); } function applyBlockGameWidget() { if (!getVal('block_game_widget', false)) return; appendBlockCSS( '.oNVQzQVi:has(.Eu5VxP6I){display:none!important}\n' + '.oNVQzQVi:has(.bTipGpIC){display:none!important}\n' + '.oNVQzQVi:has(svg [id^="gameIcon_svg"]){display:none!important}\n' + '.bTipGpIC:has(svg [id^="gameIcon_svg"]){display:none!important}' ); } function applyBlockLuckyBag() { if (!getVal('block_lucky_bag', false)) return; appendBlockCSS( '#ShortTouchLayout .ShortTouchContainer:has(.redpacket){display:none!important}\n' + '.basicPlayer[data-e2e="basicPlayer"] > pace-island[id^="island_"]:has(.ShortTouchContainer .redpacket){display:none!important}\n' + '.ShortTouchContainer:has(.redpacket){display:none!important}\n' + '[data-e2e="luckyBag-container"]{display:none!important}\n' + '[class*="luckyBag"]{display:none!important}\n' + '[class*="lucky-bag"]{display:none!important}\n' + '.lucky-bag{display:none!important}\n' + '.luckyBag{display:none!important}\n' + '[data-e2e="luckyBag"]{display:none!important}' ); } function applyBlockUserLevelIcon() { if (!getVal('block_user_level_icon', false)) return; appendBlockCSS( '#chatroom .webcast-chatroom___item *:has(>img[src*="level"]){display:none!important}\n' + '#chatroom .webcast-chatroom___item *:has(>img[src*="aweme_grade_buff"]){display:none!important}\n' + '#chatroom .webcast-chatroom___item *:has(>img[src*="league"]){display:none!important}' ); } function applyBlockVipIcon() { if (!getVal('block_vip_icon', false)) return; appendBlockCSS('#chatroom .webcast-chatroom___item *:has(>img[src*="subscribe"]){display:none!important}'); } function applyBlockFansIcon() { if (!getVal('block_fans_icon', false)) return; appendBlockCSS( '#chatroom .webcast-chatroom___item span:has(>div[style*="fansclub"]){display:none!important}\n' + '#chatroom .webcast-chatroom___item *:has(>img[src*="fansclub"]){display:none!important}' ); } function applyBlockLivePlayerControls() { if (!getVal('block_live_player_controls', false)) return; appendBlockCSS('[data-e2e="living-container"] .douyin-player-controls{display:none!important}'); } function applyBlockLivePlayBtn() { if (!getVal('block_live_play_btn', false)) return; appendBlockCSS('[data-e2e="living-container"] .douyin-player-play{display:none!important}'); } function applyBlockLiveRefreshBtn() { if (!getVal('block_live_refresh_btn', false)) return; appendBlockCSS('[data-e2e="living-container"] .douyin-player-play+slot:has(svg){display:none!important}'); } function applyBlockLiveQualityBtn() { if (!getVal('block_live_quality_btn', false)) return; appendBlockCSS('[data-e2e="living-container"] .QualitySwitchNewPlugin{display:none!important}'); } function applyBlockLiveVolumeBtn() { if (!getVal('block_live_volume_btn', false)) return; appendBlockCSS('[data-e2e="living-container"] .douyin-player-volume{display:none!important}'); } function applyBlockLiveFullscreenBtn() { if (!getVal('block_live_fullscreen_btn', false)) return; appendBlockCSS('[data-e2e="living-container"] .douyin-player-fullscreen{display:none!important}'); } function applyBlockLiveDanmakuSwitch() { if (!getVal('block_live_danmaku_switch', false)) return; appendBlockCSS('[data-e2e="living-container"] div:has(>[data-e2e="danmaku-setting-icon"]){display:none!important}'); } function applyBlockLiveGiftSetting() { if (!getVal('block_live_gift_setting', false)) return; appendBlockCSS('[data-e2e="living-container"] div:has(>[data-e2e="gift-setting"]){display:none!important}'); } // ================================================================ // 飘屏屏蔽功能 // ================================================================ function applyBlockGiftFloat() { if (getVal('block_gift_float', false)) { appendBlockCSS( '#GiftEffectLayout{display:none!important}\n' + '.GiftEffectPlugin{display:none!important}\n' + '.webcast-gift-transition{display:none!important}\n' + '.gift-effect-container{display:none!important}\n' + '.webcast-gift-effect{display:none!important}\n' + '.gift-box-effect{display:none!important}\n' + '[class*="gift-transition"]{display:none!important}\n' + '[class*="gift-effect"]{display:none!important}\n' + '.webcast-gift-effect-layout{display:none!important}\n' + '.webcast-gift-animation{display:none!important}\n' + '.GiftAnimationLayout{display:none!important}\n' + 'div[id^="gift_effect_bg_"]{display:none!important}\n' + '[data-e2e="gifts-float"]{display:none!important}\n' + '.gift-float-container{display:none!important}' ); } } function applyBlockGiftNotice() { if (!getVal('block_gift_notice', false)) return; appendBlockCSS( '.basicPlayer[data-e2e="basicPlayer"] > pace-island[id^="island_"]:has(.ShortTouchContainer):not(:has(.redpacket)){display:none!important}\n' + '#ShortTouchLayout .ShortTouchContainer:not(:has(.redpacket)){display:none!important}\n' + '#GiftTrayLayout{display:none!important}\n' + '#GiftEffectLayout{display:none!important}\n' + '#GiftMenuLayout{display:none!important}\n' + 'div[id^="gift_effect_bg_"]{display:none!important}\n' + '[class*="short-touch"]:not(:has(.redpacket)){display:none!important}' ); } function applyBlockLuckyFloat() { // 福袋口令飘屏只通过弹幕设置面板中的“福袋口令”开关控制, // 不使用CSS隐藏福袋容器,避免误伤“屏蔽福袋”开关对应的福袋活动入口。 } function tryToggleDanmakuSwitch(switchText, targetState) { const TAG = '[油猴-开关]'; // 白名单: 只在白名单文本时才进行切换 var foundSpan = null; for (var si = 0; si < document.querySelectorAll('span').length; si++) { var sp = document.querySelectorAll('span')[si]; if (sp.textContent && sp.textContent.trim() === switchText) { foundSpan = sp; break; } } if (foundSpan) { console.log(TAG, '开关已存在页面中,直接操作'); var nextEl = foundSpan.nextElementSibling; if (nextEl) { performToggle(nextEl); } else { console.log(TAG, '未找到兄弟元素'); } return; } // 查找弹幕设置图标 console.log(TAG, '寻找弹幕设置入口...'); var icon = document.querySelector('[data-e2e="danmaku-setting-icon"]') || document.querySelector('[data-e2e="danmaku-setting"]') || document.querySelector('[data-e2e*="danmaku"]'); if (!icon) { console.log(TAG, 'icon未就绪,等待渲染...'); var waitCount = 0; var waitForIcon = function() { var found = document.querySelector('[data-e2e="danmaku-setting-icon"]') || document.querySelector('[data-e2e="danmaku-setting"]') || document.querySelector('[data-e2e*="danmaku"]'); if (found) { console.log(TAG, '延迟后找到icon'); openPanelAndToggle(found); } else if (waitCount < 15) { waitCount++; managedSetTimeout(waitForIcon, 500); } else { console.log(TAG, '等待超时'); } }; managedSetTimeout(waitForIcon, 1000); return; } openPanelAndToggle(icon); function performToggle(el) { // 获取React fiber(模仿 utils.getReactInstance -> { reactFiber: ... }) var fiber = null; try { var key = Object.keys(el).find(function(k) { return k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$'); }); if (key) fiber = el[key]; } catch (e) {} if (!fiber) { console.log(TAG, '未找到React fiber'); return false; } // 模仿 WhiteSevs: utils.getReactInstance 返回 { reactFiber: rawFiber } var rect = { reactFiber: fiber }; // 严格模仿 WhiteSevs 遍历方式: // rect.reactFiber.child.child.memoizedProps.onClick // rect.reactFiber.child.memoizedProps.checked var child = rect.reactFiber && rect.reactFiber.child; var grandChild = child && child.child; var onClick = grandChild && grandChild.memoizedProps && grandChild.memoizedProps.onClick; var checked = child && child.memoizedProps && child.memoizedProps.checked; console.log(TAG, 'checked:', checked, 'onClick:', typeof onClick); if (typeof checked === 'boolean' && typeof onClick === 'function') { if (checked !== targetState) { console.log(TAG, '点击切换', switchText); try { onClick(); } catch (e) { console.error(TAG, '点击出错', e); } } else { console.log(TAG, '已是目标状态'); } return true; } // 如果上面的路径没找到,尝试从child的child的child查找(更深层遍历) if (child) { var deepFiber = child; for (var di = 0; di < 8 && deepFiber; di++) { var pp = deepFiber.memoizedProps || deepFiber.pendingProps; if (pp && typeof pp.checked === 'boolean' && typeof pp.onClick === 'function') { console.log(TAG, '嵌套找到 onClick, checked:', pp.checked); if (pp.checked !== targetState) { try { pp.onClick(); } catch (e) { console.error(TAG, '点击出错', e); } } return true; } deepFiber = deepFiber.child; } } console.log(TAG, '未找到可点击的onClick'); return false; } function waitForText(callback) { // 模仿 domUtils.waitNode: 轮询等待包含指定文本的span出现 var maxRetry = 10; var interval = 200; var tried = 0; var poll = function() { var sp = null; for (var i = 0; i < document.querySelectorAll('span').length; i++) { var s = document.querySelectorAll('span')[i]; if (s.textContent && s.textContent.trim() === switchText) { sp = s; break; } } if (sp) { console.log(TAG, '面板渲染完成,找到', switchText); callback(sp); return; } tried++; if (tried < maxRetry) { managedSetTimeout(poll, interval); } else { console.log(TAG, '等待超时,未找到', switchText); callback(null); } }; managedSetTimeout(poll, 300); } function openPanelAndToggle(iconEl) { // 获取React fiber var iconFiber = null; try { var key = Object.keys(iconEl).find(function(k) { return k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$'); }); if (key) iconFiber = iconEl[key]; } catch (e) {} if (!iconFiber) { console.log(TAG, '未找到fiber'); return; } // 查找onMouseEnter/onMouseLeave var enterFn = null, leaveFn = null; var cur = iconFiber; for (var i = 0; i < 15 && cur; i++) { var pp = cur.memoizedProps || cur.pendingProps; if (pp && typeof pp.onMouseEnter === 'function' && typeof pp.onMouseLeave === 'function') { enterFn = pp.onMouseEnter; leaveFn = pp.onMouseLeave; break; } cur = cur.return; } if (!enterFn) { console.log(TAG, '未找到onMouseEnter'); return; } console.log(TAG, '打开面板...'); enterFn(); // 模仿 domUtils.waitNode: 等待面板渲染完成后再查找 waitForText(function(sp) { try { if (!sp) { console.log(TAG, '未找到文本:', switchText); return; } // 模仿 domUtils.next($el) var nxt = sp.nextElementSibling; if (!nxt) { console.log(TAG, '未找到兄弟checkbox'); return; } console.log(TAG, '找到checkbox元素'); performToggle(nxt); } catch (error) { console.error(TAG, '出错:', error); } finally { // 关闭面板(模仿 onMouseLeave 放在finally) if (leaveFn) managedSetTimeout(leaveFn, 100); } }); } } function applyBlockChatroom() { if (!getVal('block_chatroom', false)) return; appendBlockCSS( '#chatroom{display:none!important}\n' + '#RightBackgroundLayout{display:none!important}\n' + 'div[data-e2e="living-container"]{margin-bottom:0!important}' ); } function applyBlockTopBar() { if (!getVal('block_top_bar', false)) return; appendBlockCSS( 'div[data-e2e="living-container"] div[id*="living_room_player_container"] > pace-island[id^="island_"]{display:none!important}\n' + 'xg-bar.xg-top-bar{display:none!important}\n' + '#HeaderLayout{display:none!important}' ); } function applyBlockCommentBtn() { if (!getVal('block_comment_btn', false)) return; appendBlockCSS( 'div.dy-tip-container:has([data-e2e="feed-comment-icon"]){display:none!important}\n' + '.basePlayerContainer div[aria-describedby]:has([data-e2e="feed-comment-icon"]){display:none!important}' ); } function applyBlockVideoDanmaku() { if (!getVal('block_video_danmaku', false)) return; appendBlockCSS('.basePlayerContainer .danmu{display:none!important}'); } function applyBlockLiveDanmaku() { if (!getVal('block_live_danmaku', false)) return; appendBlockCSS( 'xg-danmu.xgplayer-danmu{display:none!important}\n' + '#DanmakuLayout{display:none!important}' ); } function applyBlockLiveEmoji() { if (!getVal('block_live_emoji', false)) return; appendBlockCSS( '#chatroom .webcast-chatroom___item *:has(>img[src*="emoji"]){display:none!important}\n' + '#chatroom .webcast-chatroom___item *:has(>img[src*="picture"]){display:none!important}' ); } function applyBlockLiveRoomMsg() { if (!getVal('block_live_room_msg', false)) return; appendBlockCSS( '#chatroom .webcast-chatroom___bottom-message{display:none!important}\n' + '#chatroom > div > div > pace-island:has(div[style*="new_grade_enter"]){display:none!important}' ); } function applyVideoBgColor() { const color = getVal('video_bg_color', '#000000'); if (color === '#000000') return; appendBlockCSS( '#sliderVideo > div{background:' + color + '!important}\n' + 'xgmask{background:' + color + '!important}\n' + '.basePlayerContainer .imgBackground{background:' + color + '!important}' ); } // ================================================================ // 礼物特效屏蔽 // ================================================================ function applyGiftEffectBlock() { appendBlockCSS( '#GiftEffectLayout{display:none!important}\n' + '.GiftEffectPlugin{display:none!important}\n' + '.webcast-gift-transition{display:none!important}\n' + '.gift-effect-container{display:none!important}\n' + '.webcast-gift-effect{display:none!important}\n' + '.gift-box-effect{display:none!important}\n' + '[class*="gift-transition"]{display:none!important}\n' + '[class*="gift-effect"]{display:none!important}\n' + '.webcast-gift-effect-layout{display:none!important}\n' + '.webcast-gift-animation{display:none!important}\n' + '.GiftAnimationLayout{display:none!important}' ); } function applyFullscreenState() { const mode = getVal('live_fullscreen', 'none'); if (!isLivePage()) return; const room = getRoomId(); if (!room) return; let isWebFS = false; const spans = document.querySelectorAll('span'); for (let i = 0; i < spans.length; i++) { if (spans[i].textContent.trim() === '退出网页全屏') { isWebFS = true; break; } } const isNativeFS = !!document.fullscreenElement; if (mode === 'none') { if (isWebFS) simulateKey('y'); if (isNativeFS) { try { document.exitFullscreen(); } catch (e) { /* 忽略 */ } } roomFlags['_fs_' + room] = null; } else if (mode === 'web') { if (!isWebFS) { if (isNativeFS) { try { document.exitFullscreen(); } catch (e) { /* 忽略 */ } managedSetTimeout(() => simulateKey('y'), 300); } else { simulateKey('y'); } } roomFlags['_fs_' + room] = true; } else if (mode === 'native') { if (!isNativeFS) { if (isWebFS) { simulateKey('y'); managedSetTimeout(() => simulateKey('h'), 500); } else { simulateKey('h'); } } roomFlags['_fs_' + room] = true; } managedSetTimeout(scanAndBlock, 1000); } function scheduleFullscreen() { const mode = getVal('live_fullscreen', 'none'); if (mode === 'none' || !isLivePage()) return; const room = getRoomId(); if (!room || roomFlags['_fs_' + room]) return; managedSetInterval((timerId) => { if (!document.querySelector('video')) return; clearManagedInterval(timerId); applyFullscreenState(); }, 500, 20); } function applyMuteState() { if (!isLivePage()) return; const video = document.querySelector('video'); if (!video) return; const shouldMute = getVal('auto_mute', false); if (shouldMute === video.muted) return; simulateKey('p'); } function scheduleMute() { if (!isLivePage()) return; const room = getRoomId(); if (!room || roomFlags['_mute_' + room]) return; managedSetInterval((timerId) => { if (!document.querySelector('video')) return; clearManagedInterval(timerId); applyMuteState(); roomFlags['_mute_' + room] = true; }, 500, 20); } function detectQualities() { if (!isLivePage()) return; const room = getRoomId(); if (!room || qualityCache[room]) return; const qBtn = document.querySelector('[data-e2e="quality"]'); if (!qBtn) return; const hideStyle = document.createElement('style'); hideStyle.id = 'gb-qd-hide'; hideStyle.textContent = '[data-e2e="quality-selector"]{opacity:0!important;visibility:hidden!important;pointer-events:none!important;position:fixed!important;top:-9999px!important;left:-9999px!important}'; document.head.appendChild(hideStyle); qBtn.click(); managedSetTimeout(() => { const selector = document.querySelector('[data-e2e="quality-selector"]'); const list = []; if (selector) { for (const item of selector.children) { const t = item.textContent.trim(); if (t) list.push(t); } } qualityCache[room] = list; cleanQualityCache(); const target = getVal('live_quality', 'auto'); if (target === 'auto' && list.length > 0 && selector && selector.children[0]) { selector.children[0].click(); } else { qBtn.click(); } managedSetTimeout(() => { const s = document.getElementById('gb-qd-hide'); if (s) s.remove(); }, 200); }, 500); } function cleanQualityCache() { const keys = Object.keys(qualityCache); if (keys.length > MAX_ROOM_CACHE) { const toDelete = keys.slice(0, keys.length - MAX_ROOM_CACHE); toDelete.forEach(k => delete qualityCache[k]); } } function applyQualityState() { const target = getVal('live_quality', 'auto'); if (target === 'auto' || !isLivePage()) return; const room = getRoomId(); if (!room) return; const qBtn = document.querySelector('[data-e2e="quality"]'); if (!qBtn || qBtn.textContent.trim() === target) return; qBtn.click(); managedSetTimeout(() => { const selector = document.querySelector('[data-e2e="quality-selector"]'); if (!selector) return; const avail = {}; for (const opt of selector.children) { avail[opt.textContent.trim()] = opt; } if (avail[target]) { avail[target].click(); return; } const order = ['原画', '蓝光', '超清', '高清', '标清', '流畅']; const idx = order.indexOf(target); for (let j = idx + 1; j < order.length; j++) { if (avail[order[j]]) { avail[order[j]].click(); return; } } }, 500); } function scheduleQuality() { if (!isLivePage()) return; const room = getRoomId(); if (!room || roomFlags['_q_' + room]) return; managedSetInterval((timerId) => { if (!document.querySelector('[data-e2e="quality"]')) return; clearManagedInterval(timerId); detectQualities(); if (getVal('live_quality', 'auto') !== 'auto') applyQualityState(); roomFlags['_q_' + room] = true; }, 500, 20); } // ================================================================ // 七、应用引擎 // ================================================================ function applyAll() { clearAll(); detectTheme(); if (getVal('gift_block', false)) applyGiftBlock(); if (getVal('diamond_block', false)) applyDiamondBlock(); reconcileRoot(); if (getVal('link_block', false)) applyLinkBlock(); applyTooltipBlock(); scanAndBlock(); scheduleMute(); scheduleFullscreen(); scheduleQuality(); applyBlockChatroom(); applyBlockTopBar(); applyBlockCommentBtn(); applyBlockVideoDanmaku(); applyBlockLiveDanmaku(); applyBlockLiveEmoji(); applyBlockLiveRoomMsg(); if (getVal('video_bg_color', '#000000') !== '#000000') applyVideoBgColor(); // 新增功能 applyBlockLoginDialog(); applyBlockIdlePause(); applyBlockVideoAds(); applyBlockRelatedVideo(); applyBlockVideoRightToolbar(); applyBlockVideoTitle(); applyBlockVideoProgress(); applyBlockVideoShareBtn(); applyBlockVideoLikeBtn(); applyBlockVideoCollectBtn(); applyBlockGiftColumn(); applyBlockYellowCar(); applyBlockLuckyBag(); applyBlockGameWidget(); applyBlockUserLevelIcon(); applyBlockVipIcon(); applyBlockFansIcon(); applyBlockLivePlayerControls(); applyBlockLivePlayBtn(); applyBlockLiveRefreshBtn(); applyBlockLiveQualityBtn(); applyBlockLiveVolumeBtn(); applyBlockLiveFullscreenBtn(); applyBlockLiveDanmakuSwitch(); applyBlockLiveGiftSetting(); applyBlockGiftFloat(); applyBlockGiftNotice(); applyBlockLuckyFloat(); } // ================================================================ // 八、监听器 // ================================================================ let debounceTimer = null; const observer = new MutationObserver(mutations => { let needScan = false; for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType !== 1) continue; const cls = (typeof node.className === 'string') ? node.className : ''; if (cls.indexOf('dylive-tooltip') !== -1 || cls.indexOf('operate-text') !== -1) { needScan = true; break; } if (node.querySelector && (node.querySelector('.dylive-tooltip') || node.querySelector('.operate-text'))) { needScan = true; break; } } if (needScan) break; } if (!needScan) return; clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { applyTooltipBlock(); if (getVal('link_block', false)) applyLinkBlock(); }, 300); }); function hookSPA() { const refresh = () => { Object.keys(roomFlags).forEach(k => delete roomFlags[k]); Object.keys(qualityCache).forEach(k => delete qualityCache[k]); clearAllTimers(); managedSetInterval((timerId) => { if (!document.querySelector('video')) return; clearManagedInterval(timerId); applyAll(); }, 500, 10); }; const _p = history.pushState; const _r = history.replaceState; history.pushState = function () { _p.apply(this, arguments); refresh(); }; history.replaceState = function () { _r.apply(this, arguments); refresh(); }; window.addEventListener('popstate', refresh); document.addEventListener('fullscreenchange', () => { managedSetTimeout(scanAndBlock, 800); }); } // ================================================================ // 九、UI 样式 // ================================================================ function injectUICSS() { const css = [ /* 颜色变量 - 深色主题 (蓝白风格) */ '[data-theme="dark"]{' + '--gb-bg:rgba(18,22,36,0.92);' + '--gb-text:#f0f2f5;' + '--gb-text2:rgba(240,242,245,0.85);' + '--gb-text3:rgba(240,242,245,0.55);' + '--gb-border:rgba(255,255,255,0.08);' + '--gb-hover:rgba(255,255,255,0.06);' + '--gb-accent:#3B82F6;' + '--gb-accent-hover:#60A5FA;' + '--gb-sw-off:rgba(255,255,255,0.15);' + '--gb-sw-knob:#ffffff;' + '--gb-sidebar:rgba(18,22,36,0.95);' + '--gb-sidebar-active:rgba(59,130,246,0.15);' + '--gb-card:rgba(255,255,255,0.04);' + '--gb-card-hover:rgba(255,255,255,0.08);' + '--gb-shadow:0 8px 32px rgba(0,0,0,0.4)' + '}', /* 颜色变量 - 浅色主题 (蓝白风格) */ '[data-theme="light"]{' + '--gb-bg:rgba(245,247,250,0.96);' + '--gb-text:#1e293b;' + '--gb-text2:rgba(30,41,59,0.85);' + '--gb-text3:rgba(30,41,59,0.55);' + '--gb-border:rgba(0,0,0,0.06);' + '--gb-hover:rgba(0,0,0,0.04);' + '--gb-accent:#2563EB;' + '--gb-accent-hover:#3B82F6;' + '--gb-sw-off:rgba(0,0,0,0.12);' + '--gb-sw-knob:#ffffff;' + '--gb-sidebar:rgba(245,247,250,0.98);' + '--gb-sidebar-active:rgba(37,99,235,0.08);' + '--gb-card:rgba(255,255,255,0.85);' + '--gb-card-hover:rgba(255,255,255,1);' + '--gb-shadow:0 8px 32px rgba(0,0,0,0.06)' + '}', /* 字体变量 */ ':root{' + '--gb-fs-l1:16px;' + '--gb-fs-l2:15px;' + '--gb-fs-l3:14px;' + '--gb-fs-l4:13px;' + '--gb-fs-l5:12px;' + '--gb-fw-l1:700;' + '--gb-fw-l2:600;' + '--gb-fw-l3:500;' + '--gb-fw-l4:500;' + '--gb-fw-l5:400' + '}', /* 面板 (HyperOS 3 毛玻璃效果) */ '#gb-panel{position:fixed;z-index:2147483647;width:725px;height:520px;display:flex;flex-direction:column;background:var(--gb-bg);backdrop-filter:blur(40px) saturate(180%);-webkit-backdrop-filter:blur(40px) saturate(180%);border:1px solid var(--gb-border);border-radius:20px;box-shadow:var(--gb-shadow);font-family:-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;transition:opacity .3s cubic-bezier(.2,0,0,1),transform .3s cubic-bezier(.2,0,0,1);overflow:hidden}', '#gb-panel.gb-hidden{opacity:0;pointer-events:none;transform:scale(0.96)}', /* 头部 - 与侧边栏背景统一 */ '.gb-hdr{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;font-size:var(--gb-fs-l1);font-weight:var(--gb-fw-l1);color:var(--gb-text);border-bottom:1px solid var(--gb-border);flex-shrink:0;background:var(--gb-sidebar)}', '.gb-x{cursor:pointer;font-size:20px;color:var(--gb-text3);line-height:1;transition:all .2s;padding:4px;border-radius:8px}', '.gb-x:hover{color:var(--gb-accent);background:var(--gb-hover)}', /* 主体 */ '.gb-body{display:flex;flex:1;overflow:hidden}', /* 侧边栏 (蓝白风格) */ '.gb-sidebar{width:72px;flex-shrink:0;background:var(--gb-sidebar);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border-right:1px solid var(--gb-border);display:flex;flex-direction:column;padding:12px 0;gap:4px}', '.gb-sidebar-item{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:12px 0;cursor:pointer;transition:all .2s;color:var(--gb-text2);font-size:12px;font-weight:var(--gb-fw-l3);gap:6px;border-radius:12px;margin:0 8px}', '.gb-sidebar-item:hover{background:var(--gb-hover);color:var(--gb-text)}', '.gb-sidebar-item-on{background:var(--gb-sidebar-active);color:var(--gb-accent);font-weight:var(--gb-fw-l2)}', '.gb-sidebar-icon{font-size:20px;line-height:1;color:inherit}', '.gb-sidebar-label{line-height:1;color:inherit}', /* 内容区 */ '.gb-content-wrap{flex:1;overflow-y:auto;overflow-x:hidden;min-height:0}', '.gb-content-wrap::-webkit-scrollbar{width:3px}', '.gb-content-wrap::-webkit-scrollbar-track{background:transparent}', '.gb-content-wrap::-webkit-scrollbar-thumb{background:rgba(128,128,128,0.2);border-radius:3px}', '.gb-content-wrap::-webkit-scrollbar-thumb:hover{background:rgba(128,128,128,0.35)}', '.gb-tc{padding:14px}', /* 模块卡片 (蓝白风格) */ '.gb-mod{background:var(--gb-card);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid var(--gb-border);border-radius:14px;margin-bottom:10px;overflow:hidden;transition:all .2s}', '.gb-mod:last-child{margin-bottom:0}', '.gb-mod:hover{background:var(--gb-card-hover)}', '.gb-mhdr{display:flex;align-items:center;padding:12px 16px;cursor:pointer;transition:background .2s;user-select:none}', '.gb-mhdr:hover{background:var(--gb-hover)}', '.gb-arrow{min-width:38px;font-size:12px;color:var(--gb-text3);transition:color .2s;flex-shrink:0;text-align:left}', '.gb-detail-mode .gb-mod-detail{min-height:100%;background:transparent;border-color:transparent}', '.gb-mtitle{flex:1;font-size:var(--gb-fs-l3);font-weight:var(--gb-fw-l2);color:var(--gb-text);margin-left:10px}', '.gb-mstat{font-size:var(--gb-fs-l4);font-weight:var(--gb-fw-l4);color:var(--gb-accent);flex-shrink:0;margin-left:8px}', '.gb-mbody{padding:0 16px 10px 16px;overflow:hidden;transition:max-height .25s cubic-bezier(.2,0,0,1)}', '.gb-mbody-close{max-height:0!important;padding-top:0!important;padding-bottom:0!important}', /* 内联模块(无展开箭头) */ '.gb-mod-inline .gb-mbody{padding:0}', '.gb-mod-inline:hover{transform:none}', /* 功能行 (HyperOS 3 风格) */ '.gb-row{display:flex;justify-content:space-between;align-items:flex-start;padding:10px 0;cursor:pointer;transition:all .15s;border-bottom:1px solid rgba(128,128,128,0.08)}', '.gb-row:last-child{border-bottom:none}', '.gb-row:hover{opacity:.85}', '.gb-rleft{flex:1;min-width:0;margin-right:12px}', '.gb-rname{font-size:var(--gb-fs-l3);color:var(--gb-text);font-weight:var(--gb-fw-l3);line-height:1.4}', '.gb-desc-line{padding:4px 0 0 0;font-size:var(--gb-fs-l5);color:var(--gb-text2);font-weight:var(--gb-fw-l4);line-height:1.5}', /* 内联行(标签 + 控件同行) - 与switch行同级 */ '.gb-inline-row{display:flex;align-items:center;justify-content:space-between;padding:10px 0;cursor:default;transition:all .15s;border-bottom:1px solid rgba(128,128,128,0.08)}', '.gb-inline-row:last-child{border-bottom:none}', '.gb-inline-label{font-size:var(--gb-fs-l3);color:var(--gb-text);font-weight:var(--gb-fw-l3)}', /* 开关 (HyperOS 3 风格 - 圆角更大) */ '.gb-sw{position:relative;width:40px;height:22px;flex-shrink:0;margin-top:2px}', '.gb-sw input{position:absolute;opacity:0;width:0;height:0}', '.gb-sw-i{position:absolute;inset:0;border-radius:11px;background:var(--gb-sw-off);transition:all .25s cubic-bezier(.4,0,.2,1);cursor:pointer}', '.gb-sw-i::after{content:"";position:absolute;width:18px;height:18px;background:var(--gb-sw-knob);border-radius:50%;top:2px;left:2px;transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 4px rgba(0,0,0,0.2)}', '.gb-sw-on .gb-sw-i{background:var(--gb-accent)}', '.gb-sw-on .gb-sw-i::after{transform:translateX(18px)}', /* 下拉框 (HyperOS 3 风格) */ '.gb-dd{position:relative;width:160px}', '.gb-dd-trigger{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-radius:12px;background:var(--gb-card);border:1px solid var(--gb-border);cursor:pointer;font-size:var(--gb-fs-l3);font-weight:var(--gb-fw-l4);color:var(--gb-text);transition:all .2s;height:32px;box-sizing:border-box}', '.gb-dd-trigger:hover{border-color:var(--gb-accent);background:var(--gb-card-hover)}', '.gb-dd-arrow{font-size:10px;color:var(--gb-text3);transition:transform .2s cubic-bezier(.2,0,0,1);margin-left:8px}', '.gb-dd-open .gb-dd-arrow{transform:rotate(180deg)}', '.gb-dd-menu{position:fixed;background:rgba(22,27,44,0.96);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.12);border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.4);padding:6px 0;max-height:200px;overflow-y:auto;opacity:0;pointer-events:none;transform:translateY(-8px) scale(0.98);transition:all .2s cubic-bezier(.2,0,0,1);z-index:2147483647}', '.gb-dd-menu[data-theme="light"]{background:rgba(255,255,255,0.96);border-color:rgba(0,0,0,0.08);box-shadow:0 8px 32px rgba(0,0,0,0.1)}', '.gb-dd-menu.gb-dd-show{opacity:1;pointer-events:auto;transform:translateY(0) scale(1)}', '.gb-dd-item{display:flex;align-items:center;padding:10px 14px;font-size:var(--gb-fs-l3);font-weight:var(--gb-fw-l4);cursor:pointer;color:rgba(255,255,255,0.75);transition:all .15s;white-space:nowrap;border-radius:8px;margin:2px 6px}', '.gb-dd-menu[data-theme="light"] .gb-dd-item{color:rgba(30,41,59,0.75)}', '.gb-dd-item:hover{background:rgba(59,130,246,0.12);color:#3B82F6}', '.gb-dd-menu[data-theme="light"] .gb-dd-item:hover{background:rgba(37,99,235,0.1);color:#2563EB}', '.gb-dd-item-on{color:var(--gb-accent)!important;font-weight:var(--gb-fw-l3)}', '.gb-dd-item-on::before{content:"●";margin-right:8px;font-size:8px}', '.gb-dd-item-dis{opacity:.35;cursor:default}', '.gb-dd-item-dis:hover{background:transparent}', /* 信息页 */ '.gb-mod-info{background:var(--gb-card)!important;border-color:var(--gb-border)!important;min-height:0!important}', '.gb-mod-info .gb-mbody{display:block!important;max-height:none!important;padding:0!important;overflow:visible!important}', '.gb-info-text{display:block!important;padding:16px;font-size:var(--gb-fs-l3);font-weight:var(--gb-fw-l4);color:var(--gb-text)!important;line-height:1.8;white-space:normal;word-break:break-word}', '.gb-info-text b{color:var(--gb-text)!important;font-weight:var(--gb-fw-l2)}', '.gb-info-ver{font-size:var(--gb-fs-l1);font-weight:var(--gb-fw-l1);color:var(--gb-accent)!important;margin-bottom:8px}', '.gb-info-sep{border:none;border-top:1px solid var(--gb-border);margin:12px 0}', /* Toast (HyperOS 3 风格) */ '.gb-t{position:fixed;top:48px;left:50%;transform:translateX(-50%) translateY(-8px);z-index:2147483647;padding:10px 24px;border-radius:12px;font-size:var(--gb-fs-l2);font-weight:var(--gb-fw-l2);font-family:-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;color:#fff;background:var(--gb-accent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 4px 16px rgba(59,130,246,0.3);opacity:0;transition:all .3s cubic-bezier(.2,0,0,1);white-space:nowrap;pointer-events:none}', '.gb-t-on{opacity:1;transform:translateX(-50%) translateY(0)}' ].join('\n'); const el = document.createElement('style'); el.id = 'gb-ui-css'; el.textContent = css; (document.head || document.documentElement).appendChild(el); } // ================================================================ // 十、UI 组件 // ================================================================ function buildSwitchRow(item, onChange) { const container = document.createElement('div'); const row = document.createElement('div'); row.className = 'gb-row'; const left = document.createElement('div'); left.className = 'gb-rleft'; const nm = document.createElement('div'); nm.className = 'gb-rname'; nm.textContent = item.name; left.appendChild(nm); if (item.desc) { const dl = document.createElement('div'); dl.className = 'gb-desc-line'; dl.textContent = item.desc; left.appendChild(dl); } const sw = document.createElement('div'); sw.className = 'gb-sw'; const cb = document.createElement('input'); cb.type = 'checkbox'; cb.checked = getVal(item.key, item.def); const swI = document.createElement('span'); swI.className = 'gb-sw-i'; if (cb.checked) sw.classList.add('gb-sw-on'); sw.appendChild(cb); sw.appendChild(swI); row.appendChild(left); row.appendChild(sw); row.addEventListener('click', (e) => { e.stopPropagation(); cb.checked = !cb.checked; setVal(item.key, cb.checked); sw.classList.toggle('gb-sw-on', cb.checked); if (onChange) onChange(cb.checked); toast((cb.checked ? '✅ ' : '❎ ') + item.name); }); container.appendChild(row); return container; } let ddOpenMenu = null; let ddCloseHandlerRef = null; function buildDropdown(key, def, getOptions, onChange) { const container = document.createElement('div'); container.className = 'gb-dd'; const trigger = document.createElement('div'); trigger.className = 'gb-dd-trigger'; const triggerText = document.createElement('span'); const triggerArrow = document.createElement('span'); triggerArrow.className = 'gb-dd-arrow'; triggerArrow.textContent = '▼'; trigger.appendChild(triggerText); trigger.appendChild(triggerArrow); container.appendChild(trigger); function findLabel(val) { const opts = getOptions(); for (const o of opts) { if (o.value === val) return o.label; } return val; } function updateText() { const v = getVal(key, def); triggerText.textContent = findLabel(v); } function closeMenu() { if (ddOpenMenu) { ddOpenMenu.classList.remove('gb-dd-show'); const toRemove = ddOpenMenu; managedSetTimeout(() => { if (toRemove && toRemove.parentNode) toRemove.parentNode.removeChild(toRemove); }, 150); ddOpenMenu = null; } container.classList.remove('gb-dd-open'); if (ddCloseHandlerRef) { document.removeEventListener('click', ddCloseHandlerRef, true); ddCloseHandlerRef = null; } } function closeHandler(e) { if (!ddOpenMenu) return; if (!ddOpenMenu.contains(e.target) && !trigger.contains(e.target)) closeMenu(); } function openMenu() { if (ddOpenMenu) { closeMenu(); return; } container.classList.add('gb-dd-open'); const menu = document.createElement('div'); menu.className = 'gb-dd-menu'; menu.setAttribute('data-theme', THEME); const opts = getOptions(); const cur = getVal(key, def); opts.forEach(opt => { const item = document.createElement('div'); item.className = 'gb-dd-item'; if (opt.value === cur) item.classList.add('gb-dd-item-on'); if (opt.disabled) { item.classList.add('gb-dd-item-dis'); item.textContent = opt.label; } else { item.textContent = opt.label; item.addEventListener('click', (e) => { e.stopPropagation(); setVal(key, opt.value); updateText(); closeMenu(); if (onChange) onChange(opt); }); } menu.appendChild(item); }); const rect = trigger.getBoundingClientRect(); menu.style.left = rect.left + 'px'; menu.style.width = rect.width + 'px'; menu.style.top = (rect.bottom + 4) + 'px'; document.body.appendChild(menu); ddOpenMenu = menu; requestAnimationFrame(() => { if (!ddOpenMenu) return; const mr = menu.getBoundingClientRect(); if (mr.bottom > window.innerHeight) { menu.style.top = (rect.top - mr.height - 4) + 'px'; } menu.classList.add('gb-dd-show'); }); managedSetTimeout(() => { ddCloseHandlerRef = closeHandler; document.addEventListener('click', closeHandler, true); }, 20); } trigger.addEventListener('click', (e) => { e.stopPropagation(); openMenu(); }); updateText(); container._update = updateText; container._close = closeMenu; return container; } function getQualityOptions() { const room = getRoomId(); const cached = room ? qualityCache[room] : []; const opts = [{ value: 'auto', label: '自动(最高)' }]; if (cached && cached.length) { cached.forEach(q => opts.push({ value: q, label: q })); } else if (room) { opts.push({ value: '_loading', label: '识别中...', disabled: true }); } return opts; } function closeAllDDs() { if (ddOpenMenu) { ddOpenMenu.classList.remove('gb-dd-show'); const toRemove = ddOpenMenu; managedSetTimeout(() => { if (toRemove && toRemove.parentNode) toRemove.parentNode.removeChild(toRemove); }, 150); ddOpenMenu = null; } if (ddCloseHandlerRef) { document.removeEventListener('click', ddCloseHandlerRef, true); ddCloseHandlerRef = null; } } // ================================================================ // 十一、主界面 // ================================================================ let panel; const moduleEls = {}; function centerPanel() { if (!panel) return; panel.style.left = ((window.innerWidth - 580) / 2) + 'px'; panel.style.top = ((window.innerHeight - 520) / 2) + 'px'; } function openPanel() { if (!panel) return; centerPanel(); panel.classList.remove('gb-hidden'); refreshAllStats(); } function closePanel() { if (!panel) return; panel.classList.add('gb-hidden'); closeAllDDs(); } function createUI() { panel = document.createElement('div'); panel.id = 'gb-panel'; panel.className = 'gb-hidden'; panel.setAttribute('data-theme', THEME); const hdr = document.createElement('div'); hdr.className = 'gb-hdr'; hdr.style.cursor = 'move'; const hdrT = document.createElement('span'); hdrT.textContent = 'My-抖音优化'; const hdrX = document.createElement('span'); hdrX.className = 'gb-x'; hdrX.textContent = '×'; hdrX.addEventListener('click', closePanel); hdr.appendChild(hdrT); hdr.appendChild(hdrX); panel.appendChild(hdr); hdr.addEventListener('mousedown', (e) => { if (e.target === hdrX) return; e.preventDefault(); const rect = panel.getBoundingClientRect(); const ox = e.clientX - rect.left; const oy = e.clientY - rect.top; panel.style.transition = 'none'; function move(ev) { let nx = ev.clientX - ox; let ny = ev.clientY - oy; nx = Math.max(0, Math.min(window.innerWidth - rect.width, nx)); ny = Math.max(0, Math.min(window.innerHeight - rect.height, ny)); panel.style.left = nx + 'px'; panel.style.top = ny + 'px'; } function up() { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', up); panel.style.transition = ''; } document.addEventListener('mousemove', move); document.addEventListener('mouseup', up); }); const body = document.createElement('div'); body.className = 'gb-body'; const sidebar = document.createElement('div'); sidebar.className = 'gb-sidebar'; const sidebarItems = []; const tabContents = []; const visibleTabs = TABS.filter(tab => !HIDDEN_TAB_IDS.has(tab.id)); visibleTabs.forEach((tab, tabIdx) => { const item = document.createElement('div'); item.className = 'gb-sidebar-item' + (tabIdx === 0 ? ' gb-sidebar-item-on' : ''); item.setAttribute('data-tid', tab.id); const icon = document.createElement('span'); icon.className = 'gb-sidebar-icon'; icon.textContent = tab.icon; const label = document.createElement('span'); label.className = 'gb-sidebar-label'; label.textContent = tab.label; item.appendChild(icon); item.appendChild(label); item.addEventListener('click', () => { sidebarItems.forEach(si => si.classList.remove('gb-sidebar-item-on')); item.classList.add('gb-sidebar-item-on'); tabContents.forEach(tc => { tc.style.display = tc.getAttribute('data-tid') === tab.id ? 'block' : 'none'; tc.classList.remove('gb-detail-mode'); tc.querySelectorAll('.gb-mod').forEach(m => { m.style.display = ''; m.classList.remove('gb-mod-detail'); const mb = m.querySelector('.gb-mbody'); const ar = m.querySelector('.gb-arrow'); if (mb) mb.classList.add('gb-mbody-close'); if (ar) ar.textContent = '›'; }); }); closeAllDDs(); }); sidebar.appendChild(item); sidebarItems.push(item); }); body.appendChild(sidebar); const contentWrap = document.createElement('div'); contentWrap.className = 'gb-content-wrap'; contentWrap.addEventListener('scroll', closeAllDDs); visibleTabs.forEach((tab, tabIdx) => { const tc = document.createElement('div'); tc.className = 'gb-tc'; tc.setAttribute('data-tid', tab.id); tc.style.display = tabIdx === 0 ? 'block' : 'none'; tab.modules.forEach(mod => { const modEl = document.createElement('div'); modEl.className = 'gb-mod' + (mod.type === 'info' ? ' gb-mod-info gb-mod-inline' : ''); moduleEls[tab.id + '_' + mod.id] = modEl; const mhdr = document.createElement('div'); mhdr.className = 'gb-mhdr'; const arrow = document.createElement('span'); arrow.className = 'gb-arrow'; arrow.textContent = '›'; const title = document.createElement('span'); title.className = 'gb-mtitle'; title.textContent = mod.title; const stat = document.createElement('span'); stat.className = 'gb-mstat'; if (mod.type === 'info') { mhdr.style.display = 'none'; } else { mhdr.appendChild(arrow); mhdr.appendChild(title); mhdr.appendChild(stat); } modEl.appendChild(mhdr); const mbody = document.createElement('div'); mbody.className = 'gb-mbody'; if (mod.type !== 'info') mbody.classList.add('gb-mbody-close'); mhdr.addEventListener('click', () => { const inDetail = modEl.classList.contains('gb-mod-detail'); closeAllDDs(); if (inDetail) { tc.classList.remove('gb-detail-mode'); tab.modules.forEach(m => { const el = moduleEls[tab.id + '_' + m.id]; if (!el) return; el.style.display = ''; el.classList.remove('gb-mod-detail'); const mb = el.querySelector('.gb-mbody'); const ar = el.querySelector('.gb-arrow'); if (mb && m.type !== 'info') mb.classList.add('gb-mbody-close'); if (ar) ar.textContent = '›'; }); } else { tc.classList.add('gb-detail-mode'); tab.modules.forEach(m => { const el = moduleEls[tab.id + '_' + m.id]; if (!el) return; el.style.display = (m.id === mod.id) ? '' : 'none'; el.classList.toggle('gb-mod-detail', m.id === mod.id); const mb = el.querySelector('.gb-mbody'); const ar = el.querySelector('.gb-arrow'); if (mb && m.type !== 'info') mb.classList.toggle('gb-mbody-close', m.id !== mod.id); if (ar) ar.textContent = m.id === mod.id ? '‹ 返回' : '›'; }); } }); if (mod.type === 'switch') { mod.items.forEach(item => { if (item.hidden) return; mbody.appendChild(buildSwitchRow(item, (on) => { if (item.key === 'link_block' && !on) { document.removeEventListener('click', clickGuard, true); guardOn = false; } if (item.key === 'auto_mute') { applyMuteState(); } if (item.key === 'block_gift_float') { tryToggleDanmakuSwitch('送礼信息', !on); } if (item.key === 'block_lucky_float') { tryToggleDanmakuSwitch('福袋口令', !on); } applyAll(); refreshAllStats(); })); }); } if (mod.type === 'mixed') { if (mod.switchItems && mod.switchItems.length) { mod.switchItems.forEach(item => { mbody.appendChild(buildSwitchRow(item, () => { refreshAllStats(); })); }); } if (mod.inlineDropdowns && mod.inlineDropdowns.length) { mod.inlineDropdowns.forEach(dd => { const inlineRow = document.createElement('div'); inlineRow.className = 'gb-inline-row'; const ddLabel = document.createElement('div'); ddLabel.className = 'gb-inline-label'; ddLabel.textContent = dd.title; inlineRow.appendChild(ddLabel); const getOptions = () => dd.options; const ddRef = buildDropdown(dd.key, dd.def, getOptions, (opt) => { if (dd.key === 'live_fullscreen') { const room = getRoomId(); if (room) roomFlags['_fs_' + room] = null; applyFullscreenState(); } if (dd.key === 'live_quality') { if (opt.value !== 'auto' && isLivePage()) { const room = getRoomId(); if (room) roomFlags['_q_' + room] = null; if (!qualityCache[room]) { detectQualities(); managedSetTimeout(() => applyQualityState(), 800); } else { applyQualityState(); } } } if (dd.key === 'ui_theme') { detectTheme(); } refreshAllStats(); toast('✅ ' + dd.title + ': ' + (dd.key === 'live_quality' && opt.value === 'auto' ? '自动(最高)' : opt.label)); }); inlineRow.appendChild(ddRef); mbody.appendChild(inlineRow); }); } } if (mod.type === 'color') { const descLine = document.createElement('div'); descLine.className = 'gb-desc-line'; descLine.textContent = mod.desc || ''; mbody.appendChild(descLine); const row = document.createElement('div'); row.className = 'gb-row'; const left = document.createElement('div'); left.className = 'gb-rleft'; const nm = document.createElement('div'); nm.className = 'gb-rname'; nm.textContent = mod.title; left.appendChild(nm); row.appendChild(left); const picker = document.createElement('input'); picker.type = 'color'; picker.value = getVal(mod.key, mod.def); picker.style.cssText = 'width:36px;height:28px;border:none;padding:0;cursor:pointer;background:transparent;border-radius:4px;flex-shrink:0'; picker.addEventListener('input', () => { setVal(mod.key, picker.value); applyAll(); refreshAllStats(); }); row.appendChild(picker); mbody.appendChild(row); } if (mod.type === 'info') { const infoDiv = document.createElement('div'); infoDiv.className = 'gb-info-text'; infoDiv.innerHTML = `
My-抖音优化 ${VERSION}
简介
个人自用版抖音网页版优化脚本,用于屏蔽部分直播间控件、减少页面干扰、优化观看体验。
主要功能
直播礼物/福袋/飘屏/聊天室/播放器控件屏蔽,登录弹窗和暂停弹窗处理,主题自动切换。
免责声明
本脚本为个人自用性质的抖音网页版优化脚本,主要用于减少页面干扰、屏蔽部分控件、优化个人观看体验。脚本仅适合本人或有类似需求的用户使用,不保证适配所有页面、所有浏览器环境或抖音后续版本。

本脚本不会主动采集、上传或保存用户个人信息。由于抖音网页版结构可能随时变化,脚本中的选择器、屏蔽规则和功能开关可能出现失效、误屏蔽或显示异常等情况。使用本脚本造成的页面异常、功能不可用、账号风险或其他问题,均由使用者自行承担。

本脚本仅用于学习交流和个人使用,请勿用于商业用途、恶意用途,或违反目标网站规则的行为。
来源说明
本脚本部分设计思路参考了 WhiteSevs 发布在 ScriptCat 的《抖音优化》脚本:
https://scriptcat.org/zh-CN/script-show-page/2534

感谢原作者的开源分享。本脚本的代码主要由 AI 辅助编写与整理,作者根据个人实际使用场景进行需求描述、功能取舍、测试验证和调整修正。AI 生成内容可能存在理解偏差、兼容性不足或隐藏缺陷,因此本脚本不承诺完全稳定或长期可用。如有侵权、不适当引用或其他问题,可联系后删除或修改相关内容。
许可协议
本脚本按 GPL-3.0-only 协议发布,允许学习、使用、修改和二次分发,但请保留来源说明、参考声明和本免责声明。
更新日志
${VERSION} - 首个公开正式版。 `; mbody.appendChild(infoDiv); } modEl.appendChild(mbody); tc.appendChild(modEl); }); contentWrap.appendChild(tc); tabContents.push(tc); }); body.appendChild(contentWrap); panel.appendChild(body); document.body.appendChild(panel); document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !panel.classList.contains('gb-hidden')) { closePanel(); } }); refreshAllStats(); applyTheme(); centerPanel(); } function refreshAllStats() { TABS.filter(tab => !HIDDEN_TAB_IDS.has(tab.id)).forEach(tab => { tab.modules.forEach(mod => { const modEl = moduleEls[tab.id + '_' + mod.id]; if (!modEl) return; const stat = modEl.querySelector('.gb-mstat'); if (!stat) return; if (mod.type === 'switch') { const visibleItems = mod.items.filter(i => !i.hidden); const total = visibleItems.length; let enabled = 0; visibleItems.forEach(item => { if (getVal(item.key, item.def)) enabled++; }); stat.textContent = enabled + '/' + total; stat.style.color = enabled > 0 ? 'var(--gb-accent)' : 'var(--gb-text3)'; } else if (mod.type === 'mixed') { const visibleItems = (mod.switchItems || []).filter(i => !i.hidden); const total = visibleItems.length; let enabled = 0; visibleItems.forEach(item => { if (getVal(item.key, item.def)) enabled++; }); stat.textContent = enabled + '/' + total; stat.style.color = enabled > 0 ? 'var(--gb-accent)' : 'var(--gb-text3)'; } else if (mod.type === 'color') { const cv = getVal(mod.key, mod.def); stat.textContent = cv; stat.style.color = cv !== mod.def ? 'var(--gb-accent)' : 'var(--gb-text3)'; } else if (mod.type === 'info') { stat.textContent = VERSION; stat.style.color = 'var(--gb-text3)'; } }); }); } function toast(msg) { const t = document.createElement('div'); t.className = 'gb-t'; t.setAttribute('data-theme', THEME); t.textContent = msg; document.body.appendChild(t); requestAnimationFrame(() => t.classList.add('gb-t-on')); setTimeout(() => { t.classList.remove('gb-t-on'); setTimeout(() => t.remove(), 400); }, 1800); } // ================================================================ // 十二、初始化 // ================================================================ function init() { detectTheme(); injectUICSS(); applyAll(); const startObs = () => { if (document.body) { observer.observe(document.body, { childList: true, subtree: true }); observeDouyinTheme(); } }; if (document.body) startObs(); else document.addEventListener('DOMContentLoaded', startObs); hookSPA(); const setupUI = () => createUI(); if (document.body) setupUI(); else document.addEventListener('DOMContentLoaded', setupUI); if (window.matchMedia) { window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { if (getVal('ui_theme', 'auto') === 'auto') { detectTheme(); } }); } } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); else init(); try { GM_registerMenuCommand('打开设置', openPanel); } catch (e) { /* 忽略 */ } })();