您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
优化 Jellyfin 弹幕设置界面:分组折叠布局、控制功能集成、样式美化、响应式设计,全面提升用户体验。
// ==UserScript== // @name Jellyfin 弹幕设置界面优化增强 // @namespace https://github.com/guiyuanyuanbao/jellyfin-danmaku-beautify // @version 1.0.0 // @description 优化 Jellyfin 弹幕设置界面:分组折叠布局、控制功能集成、样式美化、响应式设计,全面提升用户体验。 // @author guiyuanyuanbao // @license MIT // @match *://*/*/web/index.html // @match *://*/web/index.html // @match *://*/*/web/ // @match *://*/web/ // @run-at document-idle // @grant none // @supportURL https://github.com/guiyuanyuanbao/jellyfin-danmaku-beautify/issues // @homepageURL https://github.com/guiyuanyuanbao/jellyfin-danmaku-beautify // ==/UserScript== (function() { 'use strict'; // 强制应用输入框样式的函数 function forceApplyInputStyles() { const targetInputs = [ '#danmakuFontFamily', '#danmakuOffsetTime', '#danmakuFontOptions' ]; targetInputs.forEach(selector => { const input = document.querySelector(selector); if (input) { console.log(`[Danmaku] 强制应用样式到: ${selector}`); // 先清除可能的border-image属性 input.style.borderImage = ''; input.style.borderImageSource = ''; input.style.borderImageSlice = ''; input.style.borderImageWidth = ''; input.style.borderImageOutset = ''; input.style.borderImageRepeat = ''; input.style.cssText = ` background: linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08)) !important; border: 2px solid rgba(169, 91, 194, 0.4) !important; border-radius: 12px !important; padding: 10px 16px !important; color: #fff !important; font-size: 14px !important; font-weight: 500 !important; min-height: 40px !important; height: 40px !important; line-height: 1.4 !important; backdrop-filter: blur(25px) !important; max-width: 100% !important; width: 100% !important; box-sizing: border-box !important; flex: 1 1 auto !important; flex-grow: 1 !important; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1) !important; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; `; // 添加焦点事件 input.addEventListener('focus', function() { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.18), rgba(0, 164, 219, 0.18))'; this.style.borderColor = 'rgba(169, 91, 194, 0.8)'; this.style.boxShadow = '0 0 0 5px rgba(169, 91, 194, 0.2), 0 6px 25px rgba(169, 91, 194, 0.35), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; this.style.transform = 'translateY(-1px) scale(1.01)'; }); // 添加失去焦点事件 input.addEventListener('blur', function() { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08))'; this.style.border = '2px solid rgba(169, 91, 194, 0.4)'; this.style.boxShadow = '0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; this.style.transform = 'translateY(0) scale(1)'; }); } }); // 也处理通用的文本输入框 const allTextInputs = document.querySelectorAll('input[type="text"], input[type="number"]'); allTextInputs.forEach(input => { if (input.id && input.id.includes('danmaku')) { console.log(`[Danmaku] 强制应用样式到通用输入框: ${input.id}`); // 先清除可能的border-image属性 input.style.borderImage = ''; input.style.borderImageSource = ''; input.style.borderImageSlice = ''; input.style.borderImageWidth = ''; input.style.borderImageOutset = ''; input.style.borderImageRepeat = ''; input.style.cssText = ` background: linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08)) !important; border: 2px solid rgba(169, 91, 194, 0.4) !important; border-radius: 12px !important; padding: 10px 16px !important; color: #fff !important; font-size: 14px !important; font-weight: 500 !important; min-height: 40px !important; height: 40px !important; line-height: 1.4 !important; backdrop-filter: blur(25px) !important; max-width: 100% !important; width: 100% !important; box-sizing: border-box !important; flex: 1 1 auto !important; flex-grow: 1 !important; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1) !important; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; `; } }); } // 添加复选框颜色动态更新 function updateCheckboxColors() { const checkboxes = document.querySelectorAll('.danmakuSidebar input[type="checkbox"], .danmakuSidebar input[type="radio"], #danmakuModal input[type="checkbox"], #danmakuModal input[type="radio"]'); checkboxes.forEach(checkbox => { checkbox.addEventListener('change', function() { if (this.checked) { this.style.border = '2px solid rgba(169, 91, 194, 0.8)'; } else { this.style.border = '2px solid rgba(128, 128, 128, 0.4)'; } }); }); } // 强制修复复选框和单选框的边框 function fixCheckboxBorders() { const checkboxes = document.querySelectorAll('.danmakuSidebar input[type="checkbox"], .danmakuSidebar input[type="radio"], #danmakuModal input[type="checkbox"], #danmakuModal input[type="radio"]'); checkboxes.forEach(checkbox => { // 清除border-image属性 checkbox.style.borderImage = ''; checkbox.style.borderImageSource = ''; checkbox.style.borderImageSlice = ''; checkbox.style.borderImageWidth = ''; checkbox.style.borderImageOutset = ''; checkbox.style.borderImageRepeat = ''; // 确保边框样式正确,未选中状态使用灰色 if (!checkbox.checked) { checkbox.style.border = '2px solid rgba(128, 128, 128, 0.4)'; } checkbox.style.borderRadius = checkbox.type === 'radio' ? '50%' : '6px'; }); } // 定期检查并应用样式 setInterval(() => { forceApplyInputStyles(); fixCheckboxBorders(); updateCheckboxColors(); }, 1000); // 在DOM加载完成后立即应用一次 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { forceApplyInputStyles(); fixCheckboxBorders(); updateCheckboxColors(); }); } else { forceApplyInputStyles(); fixCheckboxBorders(); updateCheckboxColors(); } // 监听DOM变化,检测弹幕设置对话框的创建 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === 1) { // 检查新添加的节点是否包含目标输入框 if (node.id === 'danmakuFontFamily' || node.id === 'danmakuOffsetTime' || node.id === 'danmakuFontOptions') { console.log(`[Danmaku] 检测到新增输入框: ${node.id}`); setTimeout(() => forceApplyInputStyles(), 100); } // 检查子节点中是否有目标输入框 if (node.querySelector) { const hasTargetInputs = node.querySelector('#danmakuFontFamily, #danmakuOffsetTime, #danmakuFontOptions'); if (hasTargetInputs) { console.log('[Danmaku] 检测到包含目标输入框的容器'); setTimeout(() => forceApplyInputStyles(), 100); } } if (node.id === 'danmakuModal') { // 阻止原始模态框显示并创建侧边栏 node.style.display = 'none'; createDanmakuSidebar(node); } // 检测播放器设置菜单的创建 - 更精确的选择器 if (node.classList && node.classList.contains('actionSheet') && node.querySelector('[data-id="aspectratio"]') && node.querySelector('[data-id="playbackrate"]')) { addDanmakuSettingsToMenu(node); } // 也检查子节点,以防菜单是在容器内添加的 const actionSheet = node.querySelector && node.querySelector('.actionSheet'); if (actionSheet && actionSheet.querySelector('[data-id="aspectratio"]') && actionSheet.querySelector('[data-id="playbackrate"]')) { addDanmakuSettingsToMenu(actionSheet); } // 检测并清理空白的dialogContainer if (node.classList && node.classList.contains('dialogContainer') && !node.innerHTML.trim()) { console.log('[Danmaku Settings] 发现空白dialogContainer,正在清理'); node.remove(); } } }); // 检测移除的节点,如果是弹幕模态框被移除,清理残留容器 mutation.removedNodes.forEach((node) => { if (node.nodeType === 1 && node.id === 'danmakuModal') { setTimeout(() => { cleanupEmptyDialogContainers(); }, 100); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); // 清理空白的对话框容器 function cleanupEmptyDialogContainers() { const emptyContainers = document.querySelectorAll('.dialogContainer'); emptyContainers.forEach(container => { // 检查容器是否为空或只包含空白内容 if (!container.innerHTML.trim() || (!container.querySelector('.dialog') && !container.querySelector('.actionSheet'))) { console.log('[Danmaku Settings] 清理空白dialogContainer'); container.remove(); } }); // 也清理可能残留的backdrop const emptyBackdrops = document.querySelectorAll('.dialogBackdrop'); emptyBackdrops.forEach(backdrop => { if (!backdrop.nextElementSibling || !backdrop.nextElementSibling.querySelector('.dialog, .actionSheet')) { console.log('[Danmaku Settings] 清理空白dialogBackdrop'); backdrop.remove(); } }); } // 添加弹幕设置到播放器设置菜单 function addDanmakuSettingsToMenu(actionSheet) { console.log('[Danmaku Settings] 检测到播放器设置菜单'); // 为播放器设置菜单添加特殊标识类 actionSheet.classList.add('video-player-settings-menu'); const scroller = actionSheet.querySelector('.actionSheetScroller'); if (!scroller || scroller.querySelector('[data-id="danmaku-settings"]')) { console.log('[Danmaku Settings] 菜单已存在或找不到滚动容器'); return; } // 延迟执行,确保菜单完全加载 setTimeout(() => { // 隐藏原始弹幕设置按钮 const originalDanmakuSettings = document.querySelector('#danmakuSettings'); if (originalDanmakuSettings) { originalDanmakuSettings.style.display = 'none'; } // 创建弹幕设置菜单项 const danmakuMenuItem = document.createElement('button'); danmakuMenuItem.setAttribute('is', 'emby-button'); danmakuMenuItem.setAttribute('type', 'button'); danmakuMenuItem.className = 'listItem listItem-button actionSheetMenuItem emby-button'; danmakuMenuItem.setAttribute('data-id', 'danmaku-settings'); danmakuMenuItem.innerHTML = ` <div class="listItemBody actionsheetListItemBody"> <div class="listItemBodyText actionSheetItemText">弹幕设置</div> </div> `; // 添加点击事件 danmakuMenuItem.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); console.log('[Danmaku Settings] 弹幕设置菜单项被点击'); if (originalDanmakuSettings) { originalDanmakuSettings.click(); } // 关闭设置菜单 setTimeout(() => { const backdrop = document.querySelector('.dialogBackdrop') || document.querySelector('[data-history="true"]'); if (backdrop && backdrop.contains(actionSheet)) { backdrop.click(); } else { actionSheet.remove(); } }, 100); }); // 将弹幕设置添加到循环模式之前,如果没有循环模式就添加到播放信息之前 const repeatModeItem = scroller.querySelector('[data-id="repeatmode"]'); const statsItem = scroller.querySelector('[data-id="stats"]'); if (repeatModeItem) { scroller.insertBefore(danmakuMenuItem, repeatModeItem); } else if (statsItem) { scroller.insertBefore(danmakuMenuItem, statsItem); } else { scroller.appendChild(danmakuMenuItem); } console.log('[Danmaku Settings] 弹幕设置已添加到播放器设置菜单'); }, 50); } // 创建弹幕设置侧边栏 function createDanmakuSidebar(originalModal) { // 防止创建重复的侧边栏 if (document.getElementById('danmakuSidebar')) { return; } const dialog = originalModal.querySelector('.dialog'); if (!dialog) return; const sidebar = document.createElement('div'); sidebar.id = 'danmakuSidebar'; sidebar.className = 'danmakuSidebar'; sidebar.style.cssText = ` position: fixed; top: 0; right: 0; width: 450px; max-width: 90vw; height: 100vh; background: rgba(18, 18, 20, 0.95); backdrop-filter: blur(15px); z-index: 1000000; display: flex; flex-direction: column; box-shadow: -5px 0 25px rgba(0, 0, 0, 0.5); transform: translateX(100%); transition: transform 0.3s ease-in-out; overflow: hidden; box-sizing: border-box; `; // 创建头部 const header = document.createElement('div'); header.style.cssText = ` padding: 16px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(255, 255, 255, 0.1); min-height: 60px; `; const titleEl = document.createElement('h2'); titleEl.textContent = '弹幕设置'; titleEl.style.cssText = ` color: #fff; margin: 0; font-size: 20px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; `; // 创建右侧按钮组 const buttonsContainer = document.createElement('div'); buttonsContainer.style.cssText = ` display: flex; gap: 10px; align-items: center; `; // 保存按钮 const saveButton = document.createElement('button'); saveButton.innerHTML = '保存'; saveButton.title = '保存设置'; saveButton.style.cssText = ` background: linear-gradient(135deg, #a95bc2, #00a4db); border: none; color: #fff; font-size: 14px; font-weight: 600; cursor: pointer; padding: 10px 20px; border-radius: 8px; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); min-width: 60px; `; saveButton.onclick = () => { // 触发原始保存按钮 const originalSaveButton = originalModal.querySelector('.btnSave, [data-role="button"][data-theme="b"]:not(.btnCancel)'); if (originalSaveButton) { originalSaveButton.click(); } closeDanmakuSidebar(); }; saveButton.addEventListener('mouseenter', function() { this.style.transform = 'translateY(-1px)'; this.style.boxShadow = '0 4px 12px rgba(169, 91, 194, 0.4)'; }); saveButton.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0)'; this.style.boxShadow = 'none'; }); // 取消按钮 const cancelButton = document.createElement('button'); cancelButton.innerHTML = '取消'; cancelButton.title = '取消设置'; cancelButton.style.cssText = ` background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); color: #fff; font-size: 14px; font-weight: 500; cursor: pointer; padding: 10px 20px; border-radius: 8px; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); min-width: 60px; `; cancelButton.onclick = () => { // 触发原始取消按钮 const originalCancelButton = originalModal.querySelector('.btnCancel, [data-role="button"][data-theme="a"]'); if (originalCancelButton) { originalCancelButton.click(); } closeDanmakuSidebar(); }; cancelButton.addEventListener('mouseenter', function() { this.style.background = 'rgba(255, 255, 255, 0.15)'; this.style.transform = 'translateY(-1px)'; this.style.boxShadow = '0 4px 12px rgba(255, 255, 255, 0.1)'; }); cancelButton.addEventListener('mouseleave', function() { this.style.background = 'rgba(255, 255, 255, 0.1)'; this.style.transform = 'translateY(0)'; this.style.boxShadow = 'none'; }); buttonsContainer.appendChild(saveButton); buttonsContainer.appendChild(cancelButton); header.appendChild(titleEl); header.appendChild(buttonsContainer); sidebar.appendChild(header); // 创建设置内容容器 const settingsContainer = document.createElement('div'); settingsContainer.className = 'danmaku-settings-container'; settingsContainer.style.cssText = ` flex: 1; overflow-y: auto; padding: 16px; width: 100%; max-width: 100%; box-sizing: border-box; `; sidebar.appendChild(settingsContainer); // 处理设置项 setTimeout(() => { setupDanmakuSettings(originalModal, settingsContainer); }, 100); document.body.appendChild(sidebar); // 添加样式 addDanmakuSidebarStyles(); // ESC键关闭 const handleEscape = (e) => { if (e.key === 'Escape') { closeDanmakuSidebar(); } }; document.addEventListener('keydown', handleEscape); sidebar._handleEscape = handleEscape; // 点击外部关闭 const handleOutsideClick = (e) => { // 检查是否点击了控制功能相关的原始按钮 const originalButtons = [ '#displayDanmaku', '#displayLog', '#searchDanmaku', '#addDanmakuSource' ]; // 如果点击的是原始按钮,不关闭侧边栏 for (const buttonSelector of originalButtons) { const button = document.querySelector(buttonSelector); if (button && (e.target === button || button.contains(e.target))) { return; } } // 如果点击的是侧边栏外部,才关闭侧边栏 if (sidebar && !sidebar.contains(e.target)) { closeDanmakuSidebar(); } }; setTimeout(() => { document.addEventListener('click', handleOutsideClick); sidebar._handleOutsideClick = handleOutsideClick; }, 300); // 显示侧边栏 setTimeout(() => { sidebar.style.transform = 'translateX(0)'; }, 50); // 隐藏原始按钮 hideOriginalButtons(); } // 设置弹幕设置内容 function setupDanmakuSettings(originalModal, container) { const dialog = originalModal.querySelector('.dialog'); if (!dialog) return; // 查找设置项容器 const settingsContainer = dialog.querySelector('div[style*="flex-direction: column"]'); if (!settingsContainer) return; // 获取所有设置项 const settingItems = Array.from(settingsContainer.children); // 按功能类型分类设置项 const categories = { controls: [], // 控制功能 display: [], // 显示相关 style: [], // 样式相关 filter: [], // 过滤相关 source: [], // 源相关 info: [] // 信息相关 }; settingItems.forEach(item => { const label = item.querySelector('span, label'); const labelText = label ? label.textContent.toLowerCase() : ''; // 根据标签文本和ID进行分类 if (item.querySelector('#lbAnimeTitle, #lbEpisodeTitle')) { categories.info.push(item); } else if (labelText.includes('透明度') || labelText.includes('速度') || labelText.includes('高度') || labelText.includes('字号') || labelText.includes('字体') || labelText.includes('opacity') || labelText.includes('speed') || labelText.includes('size') || labelText.includes('font')) { categories.style.push(item); } else if (labelText.includes('过滤') || labelText.includes('屏蔽') || labelText.includes('filter')) { categories.filter.push(item); } else if (labelText.includes('源') || labelText.includes('source') || labelText.includes('api')) { categories.source.push(item); } else { categories.display.push(item); } }); // 创建控制功能卡片 const controlItems = createControlFunctions(originalModal); if (controlItems && controlItems.length > 0) { categories.controls.push(...controlItems); } // 清空容器 container.innerHTML = ''; // 创建标签页结构 const tabsContainer = document.createElement('div'); tabsContainer.className = 'danmaku-tabs-container'; tabsContainer.style.cssText = ` display: flex; overflow-x: auto; padding: 16px 20px; background: rgba(0, 0, 0, 0.2); border-bottom: 1px solid rgba(255, 255, 255, 0.08); scrollbar-width: thin; scrollbar-color: rgba(169, 91, 194, 0.5) rgba(0, 0, 0, 0.1); margin: -16px -16px 20px -16px; backdrop-filter: blur(10px); gap: 4px; `; container.appendChild(tabsContainer); // 创建并添加标签 const tabs = [ { id: 'controls', title: '控制功能', items: categories.controls }, { id: 'info', title: '视频信息', items: categories.info }, { id: 'style', title: '显示样式', items: categories.style }, { id: 'display', title: '显示设置', items: categories.display }, { id: 'filter', title: '过滤设置', items: categories.filter }, { id: 'source', title: '弹幕源', items: categories.source } ]; // 过滤掉空分组 const validTabs = tabs.filter(tab => tab.items.length > 0); // 设置默认活动标签 let activeTabId = validTabs.length > 0 ? validTabs[0].id : null; // 添加标签按钮 validTabs.forEach(tab => { const tabButton = document.createElement('button'); tabButton.textContent = tab.title; tabButton.dataset.tabId = tab.id; tabButton.className = 'danmaku-tab-button'; tabButton.style.cssText = ` padding: 10px 18px; border: none; border-radius: 8px; background: ${tab.id === activeTabId ? 'linear-gradient(135deg, #a95bc2, #00a4db)' : 'rgba(255, 255, 255, 0.08)'}; color: white; font-weight: ${tab.id === activeTabId ? '600' : '500'}; font-size: 14px; cursor: pointer; white-space: nowrap; flex-shrink: 0; border: 1px solid ${tab.id === activeTabId ? 'transparent' : 'rgba(255, 255, 255, 0.1)'}; backdrop-filter: blur(10px); `; tabButton.addEventListener('click', function() { // 更新所有标签样式 document.querySelectorAll('.danmaku-tab-button').forEach(btn => { btn.style.background = 'rgba(255, 255, 255, 0.08)'; btn.style.fontWeight = '500'; btn.style.borderColor = 'rgba(255, 255, 255, 0.1)'; }); // 设置当前标签样式 this.style.background = 'linear-gradient(135deg, #a95bc2, #00a4db)'; this.style.fontWeight = '600'; this.style.borderColor = 'transparent'; // 显示对应标签的内容 showTabContent(this.dataset.tabId); }); tabsContainer.appendChild(tabButton); }); // 显示指定标签内容的函数 function showTabContent(tabId) { // 更新活动标签ID activeTabId = tabId; // 清空内容区域 - 只保留标签容器 const children = Array.from(container.children); children.forEach(child => { if (child !== tabsContainer) { child.remove(); } }); // 查找对应标签的项目 const tab = validTabs.find(t => t.id === tabId); if (!tab) return; // 如果是控制功能标签,创建弹性布局容器 if (tabId === 'controls') { const controlsContainer = document.createElement('div'); controlsContainer.style.cssText = ` display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 20px; padding: 0; `; // 直接添加控制卡片到弹性容器 tab.items.forEach(item => { controlsContainer.appendChild(item); }); container.appendChild(controlsContainer); } else { // 其他标签直接添加项目到container tab.items.forEach(item => { // 设置每个项目的样式 styleSettingItemForContent(item); container.appendChild(item); }); } } // 如果有有效标签,显示第一个标签的内容 if (activeTabId) { showTabContent(activeTabId); } } // 为内容区域的设置项添加样式 function styleSettingItemForContent(item) { // 检查是否是控制功能卡片,如果是则跳过样式处理 if (item.classList && item.classList.contains('control-card')) { return; } item.style.cssText = ` display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; margin-bottom: 12px; background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.15); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); min-height: 56px; backdrop-filter: blur(10px); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); `; // 添加悬停效果 item.addEventListener('mouseenter', function() { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08))'; this.style.borderColor = 'rgba(169, 91, 194, 0.25)'; this.style.transform = 'translateY(-1px)'; this.style.boxShadow = '0 4px 16px rgba(169, 91, 194, 0.12)'; }); item.addEventListener('mouseleave', function() { this.style.background = 'linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02))'; this.style.borderColor = 'rgba(255, 255, 255, 0.15)'; this.style.transform = 'translateY(0)'; this.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.1)'; }); // 调整标签和输入控件布局 const label = item.querySelector('span, label'); const input = item.querySelector('input, div:last-child'); if (label && input) { label.style.cssText = ` font-size: 14px; font-weight: 500; color: #fff; flex: 0 0 auto; margin-right: 20px; min-width: 120px; text-align: left; line-height: 1.4; `; if (input.tagName === 'INPUT') { input.style.flex = '1'; if (input.type === 'range') { input.style.cssText += ` max-width: 200px; height: 6px; border-radius: 3px; background: linear-gradient(135deg, #a95bc2, #00a4db); outline: none; -webkit-appearance: none; appearance: none; `; } else if (input.type === 'text' || input.type === 'number') { input.style.cssText += ` min-width: 180px; max-width: 100%; width: 100%; padding: 10px 16px; border-radius: 12px; border: 2px solid rgba(169, 91, 194, 0.4); background: linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08)); color: #fff; font-size: 14px; font-weight: 500; min-height: 40px; line-height: 1.6; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); backdrop-filter: blur(25px); box-sizing: border-box; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05); `; // 添加焦点和悬停效果 input.addEventListener('focus', function() { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.18), rgba(0, 164, 219, 0.18))'; this.style.borderColor = 'rgba(169, 91, 194, 0.8)'; this.style.boxShadow = '0 0 0 5px rgba(169, 91, 194, 0.2), 0 6px 25px rgba(169, 91, 194, 0.35), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; this.style.transform = 'translateY(-1px) scale(1.01)'; }); input.addEventListener('blur', function() { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08))'; this.style.border = '2px solid rgba(169, 91, 194, 0.4)'; this.style.boxShadow = '0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; this.style.transform = 'translateY(0) scale(1)'; }); input.addEventListener('mouseenter', function() { if (document.activeElement !== this) { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.12), rgba(0, 164, 219, 0.12))'; this.style.border = '2px solid rgba(169, 91, 194, 0.6)'; this.style.boxShadow = '0 4px 15px rgba(169, 91, 194, 0.2), inset 0 1px 2px rgba(255, 255, 255, 0.15), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; this.style.transform = 'translateY(-1px) scale(1.01)'; } }); input.addEventListener('mouseleave', function() { if (document.activeElement !== this) { this.style.background = 'linear-gradient(135deg, rgba(128, 128, 128, 0.08), rgba(160, 160, 160, 0.08))'; this.style.border = '2px solid rgba(128, 128, 128, 0.4)'; this.style.boxShadow = '0 2px 8px rgba(128, 128, 128, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; this.style.transform = 'translateY(0) scale(1)'; } }); } else if (input.type === 'checkbox' || input.type === 'radio') { input.style.cssText += ` width: 18px; height: 18px; cursor: pointer; position: relative; -webkit-appearance: none; appearance: none; background: linear-gradient(135deg, rgba(128, 128, 128, 0.08), rgba(160, 160, 160, 0.08)); border: 2px solid rgba(128, 128, 128, 0.4); border-radius: ${input.type === 'radio' ? '50%' : '6px'}; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); backdrop-filter: blur(25px); box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05); `; // 添加选中状态的伪元素效果 const updateCheckboxStyle = () => { if (input.checked) { input.style.background = 'linear-gradient(135deg, #a95bc2, #00a4db)'; input.style.border = '2px solid rgba(169, 91, 194, 0.8)'; input.style.boxShadow = '0 2px 12px rgba(169, 91, 194, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; } else { input.style.background = 'linear-gradient(135deg, rgba(128, 128, 128, 0.08), rgba(160, 160, 160, 0.08))'; input.style.border = '2px solid rgba(128, 128, 128, 0.4)'; input.style.boxShadow = '0 2px 8px rgba(128, 128, 128, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; } }; input.addEventListener('change', updateCheckboxStyle); input.addEventListener('mouseenter', function() { if (!this.checked) { this.style.border = '2px solid rgba(169, 91, 194, 0.6)'; this.style.background = 'rgba(255, 255, 255, 0.15)'; } }); input.addEventListener('mouseleave', function() { if (!this.checked) { this.style.borderColor = 'rgba(255, 255, 255, 0.3)'; this.style.background = 'rgba(255, 255, 255, 0.1)'; } }); // 初始化样式 updateCheckboxStyle(); } } else { input.style.flex = '1'; } } // 处理复选框组 - 改为横向占满布局 const checkboxGroup = item.querySelectorAll('input[type="checkbox"], input[type="radio"]'); if (checkboxGroup.length > 1) { item.style.flexDirection = 'column'; item.style.alignItems = 'flex-start'; item.style.padding = '20px'; const container = item.querySelector('div:last-child') || item; container.style.cssText = ` display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 100%; margin-top: 20px; box-sizing: border-box; `; checkboxGroup.forEach(checkbox => { const parent = checkbox.parentElement; if (parent) { parent.style.cssText = ` display: flex; align-items: center; justify-content: space-between; width: 100%; max-width: 100%; padding: 16px 20px; margin-bottom: 8px; border-radius: 12px; background: linear-gradient(135deg, rgba(169, 91, 194, 0.06), rgba(0, 164, 219, 0.06)); font-size: 14px; font-weight: 500; color: rgba(255, 255, 255, 0.95); border: 2px solid rgba(169, 91, 194, 0.4); cursor: pointer; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); min-height: 44px; backdrop-filter: blur(25px); position: relative; overflow: hidden; box-sizing: border-box; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.1), inset 0 1px 2px rgba(255, 255, 255, 0.08), inset 0 -1px 1px rgba(0, 0, 0, 0.03); `; checkbox.style.cssText = ` margin-right: 0; margin-left: 0; order: 1; width: 22px; height: 22px; cursor: pointer; position: relative; -webkit-appearance: none; appearance: none; background: linear-gradient(135deg, rgba(128, 128, 128, 0.08), rgba(160, 160, 160, 0.08)); border: 2px solid rgba(128, 128, 128, 0.4); border-radius: ${checkbox.type === 'radio' ? '50%' : '6px'}; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); backdrop-filter: blur(25px); flex-shrink: 0; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05); `; // 获取标签文本并设置右对齐 const labelText = parent.childNodes; labelText.forEach(node => { if (node.nodeType === Node.TEXT_NODE && node.textContent.trim()) { const span = document.createElement('span'); span.textContent = node.textContent.trim(); span.style.cssText = ` flex: 1; text-align: right; order: 2; margin-right: 12px; line-height: 1.4; word-wrap: break-word; overflow: hidden; max-width: calc(100% - 40px); box-sizing: border-box; `; parent.replaceChild(span, node); } }); // 创建勾选标记或圆点 let indicator = null; if (checkbox.type === 'checkbox') { indicator = document.createElement('div'); indicator.className = 'check-mark'; indicator.style.cssText = ` position: absolute; left: 5px; top: 1px; width: 6px; height: 10px; border: solid white; border-width: 0 2px 2px 0; transform: rotate(45deg) scale(0); transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); opacity: 0; `; checkbox.appendChild(indicator); } else if (checkbox.type === 'radio') { indicator = document.createElement('div'); indicator.className = 'radio-dot'; indicator.style.cssText = ` position: absolute; left: 50%; top: 50%; width: 8px; height: 8px; background: white; border-radius: 50%; transform: translate(-50%, -50%) scale(0); transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); opacity: 0; `; checkbox.appendChild(indicator); } // 添加选中状态样式 const updateStyle = () => { const indicator = checkbox.querySelector('.check-mark, .radio-dot'); if (checkbox.checked) { checkbox.style.background = 'linear-gradient(135deg, #a95bc2, #00a4db)'; checkbox.style.border = '2px solid rgba(169, 91, 194, 0.8)'; checkbox.style.boxShadow = '0 2px 12px rgba(169, 91, 194, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; checkbox.style.transform = 'scale(1.05)'; parent.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.15), rgba(0, 164, 219, 0.15))'; parent.style.border = '2px solid rgba(169, 91, 194, 0.6)'; parent.style.boxShadow = '0 2px 12px rgba(169, 91, 194, 0.25), inset 0 1px 2px rgba(255, 255, 255, 0.15), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; // 显示指示器 if (indicator) { indicator.style.transform = checkbox.type === 'radio' ? 'translate(-50%, -50%) scale(1)' : 'rotate(45deg) scale(1)'; indicator.style.opacity = '1'; } } else { checkbox.style.background = 'linear-gradient(135deg, rgba(128, 128, 128, 0.08), rgba(160, 160, 160, 0.08))'; checkbox.style.border = '2px solid rgba(128, 128, 128, 0.4)'; checkbox.style.boxShadow = '0 2px 8px rgba(128, 128, 128, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05)'; checkbox.style.transform = 'scale(1)'; parent.style.background = 'linear-gradient(135deg, rgba(128, 128, 128, 0.06), rgba(160, 160, 160, 0.06))'; parent.style.border = '2px solid rgba(128, 128, 128, 0.2)'; parent.style.boxShadow = '0 2px 8px rgba(128, 128, 128, 0.1), inset 0 1px 2px rgba(255, 255, 255, 0.08), inset 0 -1px 1px rgba(0, 0, 0, 0.03)'; // 隐藏指示器 if (indicator) { indicator.style.transform = checkbox.type === 'radio' ? 'translate(-50%, -50%) scale(0)' : 'rotate(45deg) scale(0)'; indicator.style.opacity = '0'; } } }; checkbox.addEventListener('change', updateStyle); parent.addEventListener('mouseenter', function() { if (!checkbox.checked) { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08))'; this.style.border = '2px solid rgba(169, 91, 194, 0.4)'; this.style.transform = 'translateY(-1px)'; this.style.boxShadow = '0 4px 12px rgba(169, 91, 194, 0.15), inset 0 1px 1px rgba(255, 255, 255, 0.15)'; checkbox.style.border = '2px solid rgba(169, 91, 194, 0.6)'; checkbox.style.background = 'linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(169, 91, 194, 0.1))'; checkbox.style.transform = 'scale(1.1)'; } else { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.2), rgba(0, 164, 219, 0.2))'; this.style.border = '2px solid rgba(169, 91, 194, 0.45)'; this.style.transform = 'translateY(-1px)'; this.style.boxShadow = '0 4px 16px rgba(169, 91, 194, 0.3), inset 0 1px 1px rgba(255, 255, 255, 0.2)'; checkbox.style.transform = 'scale(1.15)'; } }); parent.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0)'; updateStyle(); }); // 初始化样式 updateStyle(); parent.addEventListener('click', function(e) { // 阻止事件冒泡和默认行为 e.preventDefault(); e.stopPropagation(); // 如果点击的不是复选框本身,则触发复选框点击 if (e.target !== checkbox) { checkbox.click(); } }); // 确保复选框本身的点击事件不会被阻止 checkbox.addEventListener('click', function(e) { e.stopPropagation(); }); } }); } } // 创建控制功能区域 function createControlFunctions(originalModal) { const controlItems = []; const danmukuButton = document.querySelector('#displayDanmaku'); const logButton = document.querySelector('#displayLog'); const searchButton = document.querySelector('#searchDanmaku'); const addSourceButton = document.querySelector('#addDanmakuSource'); // 添加弹幕开关控制项 if (danmukuButton) { // 检查当前弹幕显示状态 - 通过图标判断 const danmukuIcon = danmukuButton.querySelector('.material-icons'); let isDanmukuEnabled = true; // 默认认为是开启的 if (danmukuIcon) { // 如果图标是comments_disabled,则弹幕是关闭的 isDanmukuEnabled = !danmukuIcon.classList.contains('comments_disabled'); } const danmakuSwitchItem = document.createElement('div'); danmakuSwitchItem.className = 'control-item control-card'; danmakuSwitchItem.style.cssText = ` display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding: 16px 20px; background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.15); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); min-height: 64px; flex: 1 1 calc(50% - 8px); min-width: 280px; backdrop-filter: blur(10px); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); `; danmakuSwitchItem.innerHTML = ` <div class="control-info" style="display: flex; align-items: center; flex: 1;"> <div class="control-text"> <div style="font-size: 15px; font-weight: 600; color: #fff; margin-bottom: 2px;">弹幕显示</div> <div style="font-size: 12px; color: rgba(255, 255, 255, 0.7);">控制弹幕的显示与隐藏</div> </div> </div> <label class="modern-switch"> <input type="checkbox" ${isDanmukuEnabled ? 'checked' : ''}> <span class="modern-slider"></span> </label> `; // 添加hover效果 danmakuSwitchItem.addEventListener('mouseenter', function() { this.style.background = 'linear-gradient(135deg, rgba(169, 91, 194, 0.12), rgba(0, 164, 219, 0.12))'; this.style.border = '2px solid rgba(169, 91, 194, 0.4)'; this.style.transform = 'translateY(-2px)'; this.style.boxShadow = '0 8px 25px rgba(169, 91, 194, 0.15)'; }); danmakuSwitchItem.addEventListener('mouseleave', function() { this.style.background = 'linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02))'; this.style.borderColor = 'rgba(255, 255, 255, 0.15)'; this.style.transform = 'translateY(0)'; this.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.1)'; }); const checkbox = danmakuSwitchItem.querySelector('input[type="checkbox"]'); let isUpdating = false; checkbox.addEventListener('change', function(e) { e.stopPropagation(); if (isUpdating) return; isUpdating = true; // 点击弹幕开关按钮 danmukuButton.click(); setTimeout(() => { // 检查弹幕图标状态以更新复选框 const currentIcon = danmukuButton.querySelector('.material-icons'); if (currentIcon) { const isEnabled = !currentIcon.classList.contains('comments_disabled');; checkbox.checked = isEnabled; } isUpdating = false; }, 200); }); // 监听弹幕图标状态变化 if (danmukuIcon) { const iconObserver = new MutationObserver((mutations) => { if (isUpdating) return; mutations.forEach((mutation) => { if (mutation.type === 'characterData' || mutation.type === 'childList' || (mutation.type === 'attributes' && (mutation.attributeName === 'class' || mutation.attributeName === 'textContent'))) { const currentIcon = danmukuButton.querySelector('.material-icons'); if (currentIcon) { const isEnabled = currentIcon.textContent.trim() !== 'comments_disabled'; if (checkbox.checked !== isEnabled) { checkbox.checked = isEnabled; } } } }); }); // 观察图标元素的变化 iconObserver.observe(danmukuIcon, { characterData: true, childList: true, attributes: true, subtree: true }); // 观察整个按钮的变化 iconObserver.observe(danmukuButton, { childList: true, attributes: true, subtree: true }); } controlItems.push(danmakuSwitchItem); } // 添加日志开关控制项 if (logButton) { const debugInfo = document.querySelector('#debugInfo'); let isLogEnabled = false; if (debugInfo) { const displayStyle = window.getComputedStyle(debugInfo).display; isLogEnabled = displayStyle !== 'none'; } const logSwitchItem = document.createElement('div'); logSwitchItem.className = 'control-item control-card'; logSwitchItem.style.cssText = ` display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding: 16px 20px; background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.15); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); min-height: 64px; flex: 1 1 calc(50% - 8px); min-width: 280px; backdrop-filter: blur(10px); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); `; logSwitchItem.innerHTML = ` <div class="control-info" style="display: flex; align-items: center; flex: 1;"> <div class="control-text"> <div style="font-size: 15px; font-weight: 600; color: #fff; margin-bottom: 2px;">日志显示</div> <div style="font-size: 12px; color: rgba(255, 255, 255, 0.7);">显示调试信息和日志</div> </div> </div> <label class="modern-switch"> <input type="checkbox" ${isLogEnabled ? 'checked' : ''}> <span class="modern-slider"></span> </label> `; // 添加hover效果 logSwitchItem.addEventListener('mouseenter', function() { this.style.background = 'linear-gradient(135deg, rgba(76, 175, 80, 0.12), rgba(33, 150, 243, 0.12))'; this.style.borderColor = 'rgba(76, 175, 80, 0.4)'; this.style.transform = 'translateY(-2px)'; this.style.boxShadow = '0 8px 25px rgba(76, 175, 80, 0.15)'; }); logSwitchItem.addEventListener('mouseleave', function() { this.style.background = 'linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02))'; this.style.borderColor = 'rgba(255, 255, 255, 0.15)'; this.style.transform = 'translateY(0)'; this.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.1)'; }); const checkbox = logSwitchItem.querySelector('input[type="checkbox"]'); let isUpdating = false; checkbox.addEventListener('change', function(e) { e.stopPropagation(); if (isUpdating) return; isUpdating = true; logButton.click(); setTimeout(() => { const currentDebugInfo = document.querySelector('#debugInfo'); if (currentDebugInfo) { const currentDisplayStyle = window.getComputedStyle(currentDebugInfo).display; const newLogEnabled = currentDisplayStyle !== 'none'; checkbox.checked = newLogEnabled; } isUpdating = false; }, 200); }); // 监听状态变化 if (debugInfo) { const logStatusObserver = new MutationObserver((mutations) => { if (isUpdating) return; mutations.forEach((mutation) => { if (mutation.type === 'attributes' && mutation.attributeName === 'style') { const currentDebugInfo = document.querySelector('#debugInfo'); if (currentDebugInfo) { const currentDisplayStyle = window.getComputedStyle(currentDebugInfo).display; const currentLogEnabled = currentDisplayStyle !== 'none'; if (checkbox.checked !== currentLogEnabled) { checkbox.checked = currentLogEnabled; } } } }); }); logStatusObserver.observe(debugInfo, { attributes: true, attributeFilter: ['style'] }); } controlItems.push(logSwitchItem); } // 添加搜索弹幕控制项 if (searchButton) { const searchItem = document.createElement('div'); searchItem.className = 'control-item control-card'; searchItem.style.cssText = ` display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding: 16px 20px; background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.15); cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); min-height: 64px; flex: 1 1 calc(50% - 8px); min-width: 280px; backdrop-filter: blur(10px); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); `; searchItem.innerHTML = ` <div class="control-info" style="display: flex; align-items: center; flex: 1;"> <div class="control-text"> <div style="font-size: 15px; font-weight: 600; color: #fff; margin-bottom: 2px;">弹幕搜索</div> <div style="font-size: 12px; color: rgba(255, 255, 255, 0.7);">搜索视频弹幕</div> </div> </div> <div class="control-action" style=" padding: 6px 12px; background: rgba(0, 188, 212, 0.15); border-radius: 6px; color: #00BCD4; font-size: 12px; font-weight: 500; border: 1px solid rgba(0, 188, 212, 0.25); ">搜索</div> `; searchItem.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); searchButton.click(); }); searchItem.addEventListener('mouseenter', function() { this.style.background = 'linear-gradient(135deg, rgba(0, 188, 212, 0.12), rgba(0, 229, 255, 0.12))'; this.style.borderColor = 'rgba(0, 188, 212, 0.4)'; this.style.transform = 'translateY(-2px)'; this.style.boxShadow = '0 8px 25px rgba(0, 188, 212, 0.15)'; }); searchItem.addEventListener('mouseleave', function() { this.style.background = 'linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02))'; this.style.borderColor = 'rgba(255, 255, 255, 0.15)'; this.style.transform = 'translateY(0)'; this.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.1)'; }); controlItems.push(searchItem); } // 添加增加弹幕源控制项 if (addSourceButton) { const addSourceItem = document.createElement('div'); addSourceItem.className = 'control-item control-card'; addSourceItem.style.cssText = ` display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding: 16px 20px; background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.15); cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); min-height: 64px; flex: 1 1 calc(50% - 8px); min-width: 280px; backdrop-filter: blur(10px); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); `; addSourceItem.innerHTML = ` <div class="control-info" style="display: flex; align-items: center; flex: 1;"> <div class="control-text"> <div style="font-size: 15px; font-weight: 600; color: #fff; margin-bottom: 2px;">增加弹幕源</div> <div style="font-size: 12px; color: rgba(255, 255, 255, 0.7);">添加新的弹幕数据源,如B站播放链接</div> </div> </div> <div class="control-action" style=" padding: 6px 12px; background: rgba(255, 152, 0, 0.15); border-radius: 6px; color: #FF9800; font-size: 12px; font-weight: 500; border: 1px solid rgba(255, 152, 0, 0.25); ">添加</div> `; addSourceItem.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); addSourceButton.click(); }); addSourceItem.addEventListener('mouseenter', function() { this.style.background = 'linear-gradient(135deg, rgba(255, 152, 0, 0.12), rgba(255, 193, 7, 0.12))'; this.style.borderColor = 'rgba(255, 152, 0, 0.4)'; this.style.transform = 'translateY(-2px)'; this.style.boxShadow = '0 8px 25px rgba(255, 152, 0, 0.15)'; }); addSourceItem.addEventListener('mouseleave', function() { this.style.background = 'linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02))'; this.style.borderColor = 'rgba(255, 255, 255, 0.15)'; this.style.transform = 'translateY(0)'; this.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.1)'; }); controlItems.push(addSourceItem); } return controlItems.length > 0 ? controlItems : null; } // 关闭弹幕侧边栏 function closeDanmakuSidebar() { const sidebar = document.getElementById('danmakuSidebar'); if (!sidebar) return; sidebar.style.transform = 'translateX(100%)'; if (sidebar._handleEscape) { document.removeEventListener('keydown', sidebar._handleEscape); } if (sidebar._handleOutsideClick) { document.removeEventListener('click', sidebar._handleOutsideClick); } setTimeout(() => { sidebar.parentNode?.removeChild(sidebar); // 清理原始模态框 const originalModal = document.getElementById('danmakuModal'); if (originalModal) { originalModal.remove(); } cleanupEmptyDialogContainers(); }, 300); } // 隐藏原始按钮 function hideOriginalButtons() { setTimeout(() => { const originalLogButton = document.querySelector('#displayLog'); const searchButton = document.querySelector('#searchDanmaku'); const addSourceButton = document.querySelector('#addDanmakuSource'); const danmakuSettingsButton = document.querySelector('#danmakuSettings'); [originalLogButton, searchButton, addSourceButton, danmakuSettingsButton].forEach(btn => { if (btn) btn.style.display = 'none'; }); }, 100); } // 添加侧边栏样式 function addDanmakuSidebarStyles() { if (document.getElementById('danmakuSidebarStyles')) return; const style = document.createElement('style'); style.id = 'danmakuSidebarStyles'; style.textContent = ` /* 全局复选框和单选框容器约束 */ .danmakuSidebar label, .danmakuSidebar .checkbox-container, .danmakuSidebar .radio-container, #danmakuModal label, #danmakuModal .checkbox-container, #danmakuModal .radio-container { max-width: 100% !important; box-sizing: border-box !important; overflow: hidden !important; word-wrap: break-word !important; } /* 复选框组容器约束 */ .danmakuSidebar div[style*="flex-direction: column"], #danmakuModal div[style*="flex-direction: column"] { max-width: 100% !important; box-sizing: border-box !important; overflow: hidden !important; } /* 现代化动画效果 */ @keyframes checkbox-scale { 0% { transform: scale(1); } 50% { transform: scale(0.95); } 100% { transform: scale(1.05); } } @keyframes input-focus-pulse { 0% { box-shadow: 0 0 0 0 rgba(169, 91, 194, 0.4); } 70% { box-shadow: 0 0 0 8px rgba(169, 91, 194, 0); } 100% { box-shadow: 0 0 0 0 rgba(169, 91, 194, 0); } } /* 滚动条美化 */ .danmakuSidebar .danmaku-settings-container::-webkit-scrollbar { width: 6px; } .danmakuSidebar .danmaku-settings-container::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.1); border-radius: 3px; } .danmakuSidebar .danmaku-settings-container::-webkit-scrollbar-thumb { background: linear-gradient(135deg, #a95bc2, #00a4db); border-radius: 3px; } .danmakuSidebar .danmaku-settings-container::-webkit-scrollbar-thumb:hover { background: linear-gradient(135deg, #b766d1, #0bb4f0); } .danmakuSidebar button:hover { transform: translateY(-2px); box-shadow: 0 4px 16px rgba(169, 91, 194, 0.3); background: linear-gradient(135deg, #b766d1, #0bb4f0); } .danmakuSidebar button:active { transform: translateY(0); box-shadow: 0 2px 8px rgba(169, 91, 194, 0.4); animation: checkbox-scale 0.2s ease-out; } /* 增强的标签按钮样式 */ .danmaku-tab-button { position: relative; } /* 控制卡片增强效果 */ .control-card { position: relative; overflow: hidden; } .control-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(135deg, rgba(169, 91, 194, 0.05), rgba(0, 164, 219, 0.05)); opacity: 0; transition: opacity 0.3s ease; pointer-events: none; } .control-card:hover::before { opacity: 1; } /* 标签容器滚动条样式 */ .danmaku-tabs-container::-webkit-scrollbar { height: 4px; } .danmaku-tabs-container::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.1); border-radius: 2px; } .danmaku-tabs-container::-webkit-scrollbar-thumb { background: linear-gradient(135deg, #a95bc2, #00a4db); border-radius: 2px; } /* 标签按钮样式优化 */ .danmaku-tab-button { font-size: 14px; font-weight: 500; letter-spacing: 0.3px; } /* 现代化的输入范围滑块样式 */ .danmakuSidebar input[type="range"] { -webkit-appearance: none; appearance: none; height: 6px; border-radius: 3px; outline: none; background: linear-gradient(135deg, #a95bc2, #00a4db); cursor: pointer; } .danmakuSidebar input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; border-radius: 50%; background: linear-gradient(135deg, #a95bc2, #00a4db); cursor: pointer; box-shadow: 0 2px 6px rgba(169, 91, 194, 0.3); transition: all 0.3s ease; } .danmakuSidebar input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.1); box-shadow: 0 3px 8px rgba(169, 91, 194, 0.5); } .danmakuSidebar input[type="range"]::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: linear-gradient(135deg, #a95bc2, #00a4db); cursor: pointer; border: none; box-shadow: 0 2px 6px rgba(169, 91, 194, 0.3); } /* 现代化选择框样式 - 增强版 */ .danmakuSidebar select, #danmakuModal select { background: linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08)) !important; border: 2px solid rgba(169, 91, 194, 0.4) !important; border-radius: 12px !important; padding: 10px 16px !important; color: #fff !important; font-size: 14px !important; font-weight: 500 !important; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1) !important; backdrop-filter: blur(25px) !important; min-height: 40px !important; cursor: pointer !important; -webkit-appearance: none !important; appearance: none !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='rgba(169,91,194,0.8)' viewBox='0 0 16 16'%3e%3cpath d='m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z'/%3e%3c/svg%3e") !important; background-repeat: no-repeat !important; background-position: right 16px center !important; background-size: 14px !important; padding-right: 50px !important; width: 100% !important; max-width: 100% !important; min-width: 180px !important; box-sizing: border-box !important; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } .danmakuSidebar select:focus, #danmakuModal select:focus { background: linear-gradient(135deg, rgba(169, 91, 194, 0.18), rgba(0, 164, 219, 0.18)) !important; border-color: rgba(169, 91, 194, 0.8) !important; box-shadow: 0 0 0 5px rgba(169, 91, 194, 0.2), 0 6px 25px rgba(169, 91, 194, 0.35), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; outline: none !important; transform: translateY(-1px) scale(1.01) !important; animation: input-focus-pulse 1.5s ease-out !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='rgba(169,91,194,1)' viewBox='0 0 16 16'%3e%3cpath d='m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z'/%3e%3c/svg%3e") !important; } .danmakuSidebar select:hover:not(:focus), #danmakuModal select:hover:not(:focus) { background: linear-gradient(135deg, rgba(169, 91, 194, 0.12), rgba(0, 164, 219, 0.12)) !important; border: 2px solid rgba(169, 91, 194, 0.6) !important; box-shadow: 0 4px 15px rgba(169, 91, 194, 0.2), inset 0 1px 2px rgba(255, 255, 255, 0.15), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; transform: translateY(-1px) scale(1.01) !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='rgba(169,91,194,0.9)' viewBox='0 0 16 16'%3e%3cpath d='m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z'/%3e%3c/svg%3e") !important; } .danmakuSidebar select option, #danmakuModal select option { background: rgba(40, 40, 40, 0.95) !important; color: #fff !important; padding: 8px 12px !important; border: none !important; } .danmakuSidebar select option:hover, #danmakuModal select option:hover { background: rgba(169, 91, 194, 0.3) !important; } /* 输入框验证状态样式 */ .danmakuSidebar input[type="text"].valid, .danmakuSidebar input[type="number"].valid, #danmakuModal input[type="text"].valid, #danmakuModal input[type="number"].valid { border-color: rgba(76, 175, 80, 0.7) !important; box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2), 0 2px 8px rgba(76, 175, 80, 0.15) !important; } .danmakuSidebar input[type="text"].invalid, .danmakuSidebar input[type="number"].invalid, #danmakuModal input[type="text"].invalid, #danmakuModal input[type="number"].invalid { border-color: rgba(244, 67, 54, 0.7) !important; box-shadow: 0 0 0 2px rgba(244, 67, 54, 0.2), 0 2px 8px rgba(244, 67, 54, 0.15) !important; animation: shake 0.3s ease-in-out !important; } @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } } /* 加载状态效果 */ .loading-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.3); backdrop-filter: blur(2px); display: flex; align-items: center; justify-content: center; border-radius: 12px; opacity: 0; visibility: hidden; transition: all 0.3s ease; } .loading-overlay.active { opacity: 1; visibility: visible; } .loading-spinner { width: 24px; height: 24px; border: 2px solid rgba(255, 255, 255, 0.3); border-top: 2px solid #fff; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* 工具提示样式 */ .tooltip { position: absolute; background: rgba(0, 0, 0, 0.9); color: white; padding: 8px 12px; border-radius: 6px; font-size: 12px; white-space: nowrap; z-index: 10000; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; pointer-events: none; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.1); } .tooltip.show { opacity: 1; transform: translateY(0); } .tooltip::before { content: ''; position: absolute; top: -5px; left: 50%; transform: translateX(-50%); border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 5px solid rgba(0, 0, 0, 0.9); } /* 现代化输入框样式 - 增强版 */ .danmakuSidebar input[type="text"], .danmakuSidebar input[type="number"] { background: linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08)); border: 2px solid rgba(169, 91, 194, 0.4); border-radius: 12px; padding: 10px 16px; color: #fff; font-size: 14px; font-weight: 500; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); backdrop-filter: blur(25px); box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05); position: relative; min-height: 40px; height: 40px; line-height: 1.4; max-width: 100%; width: 100%; box-sizing: border-box; min-width: 120px; } .danmakuSidebar input[type="text"]:focus, .danmakuSidebar input[type="number"]:focus { background: linear-gradient(135deg, rgba(169, 91, 194, 0.18), rgba(0, 164, 219, 0.18)); border-color: rgba(169, 91, 194, 0.8); box-shadow: 0 0 0 5px rgba(169, 91, 194, 0.2), 0 6px 25px rgba(169, 91, 194, 0.35), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05); outline: none; transform: translateY(-1px) scale(1.01); animation: input-focus-pulse 1.5s ease-out; } .danmakuSidebar input[type="text"]:hover:not(:focus), .danmakuSidebar input[type="number"]:hover:not(:focus) { background: linear-gradient(135deg, rgba(169, 91, 194, 0.12), rgba(0, 164, 219, 0.12)); border: 2px solid rgba(169, 91, 194, 0.6); box-shadow: 0 4px 15px rgba(169, 91, 194, 0.2), inset 0 1px 2px rgba(255, 255, 255, 0.15), inset 0 -1px 1px rgba(0, 0, 0, 0.05); transform: translateY(-0.5px) scale(1.005); } .danmakuSidebar input[type="text"]::placeholder, .danmakuSidebar input[type="number"]::placeholder { color: rgba(255, 255, 255, 0.5); font-weight: 400; transition: color 0.3s ease; } .danmakuSidebar input[type="text"]:focus::placeholder, .danmakuSidebar input[type="number"]:focus::placeholder { color: rgba(255, 255, 255, 0.7); } /* 响应式设计 */ @media (max-width: 600px) { .danmakuSidebar { width: 95% !important; max-width: none !important; } .danmaku-tab-button { padding: 8px 12px !important; font-size: 13px !important; } .control-card { flex: 1 1 100% !important; min-width: 100% !important; } } @media (max-width: 400px) { .control-card .control-info { flex-direction: column; align-items: flex-start; text-align: left; } .control-card .control-icon { margin-bottom: 8px; margin-right: 0 !important; } } `; document.head.appendChild(style); } function modifyDanmakuModal(modal) { // 不再修改原始模态框,因为我们使用侧边栏替代 // 原始模态框会被隐藏,侧边栏会在 createDanmakuSidebar 中创建 } // 添加CSS样式 const style = document.createElement('style'); style.textContent = ` /* 强制约束复选框和单选框容器宽度 */ .danmakuSidebar *, #danmakuModal * { box-sizing: border-box !important; } .danmakuSidebar label, .danmakuSidebar input[type="checkbox"]:parent, .danmakuSidebar input[type="radio"]:parent, #danmakuModal label, #danmakuModal input[type="checkbox"]:parent, #danmakuModal input[type="radio"]:parent { max-width: 100% !important; overflow: hidden !important; word-wrap: break-word !important; text-overflow: ellipsis !important; } /* 弹幕设置对话框分组样式 */ #danmakuModal .dialog { max-height: 85vh; overflow-y: auto; scrollbar-width: thin; scrollbar-color: rgba(169, 91, 194, 0.5) rgba(255, 255, 255, 0.1); } #danmakuModal .dialog::-webkit-scrollbar { width: 6px; } #danmakuModal .dialog::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.1); border-radius: 3px; } #danmakuModal .dialog::-webkit-scrollbar-thumb { background: linear-gradient(180deg, #a95bc2, #00a4db); border-radius: 3px; } /* 对话框标题样式 */ #danmakuModal .dialog h1, #danmakuModal .dialog h2, #danmakuModal .dialog h3 { color: #fff; font-weight: 600; margin-bottom: 15px; text-align: center; font-size: 18px; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } /* 隐藏原始位置的按钮 */ #displayLog, #searchDanmaku, #addDanmakuSource, #danmakuSettings, #sendDanmaku { display: none !important; } /* 调整播放器设置菜单位置 - 距离底部5%屏幕高度,位于右侧 - 仅在视频播放界面生效 */ .actionSheet.centeredDialog:has([data-id="aspectratio"]):has([data-id="playbackrate"]), .actionSheet.centeredDialog.video-player-settings-menu { position: fixed !important; bottom: 5vh !important; top: auto !important; /* right: 20px !important; */ /* left: auto !important; */ transform: none !important; margin: 0 !important; } .actionSheet.centeredDialog:has([data-id="aspectratio"]):has([data-id="playbackrate"])[style*="top:"], .actionSheet.centeredDialog:has([data-id="aspectratio"]):has([data-id="playbackrate"])[style*="left:"], .actionSheet.centeredDialog.video-player-settings-menu[style*="top:"], .actionSheet.centeredDialog.video-player-settings-menu[style*="left:"] { bottom: 5vh !important; top: auto !important; /* right: 20px !important; */ /* left: auto !important; */ transform: none !important; } /* 播放器设置菜单优化 - 仅在视频播放界面生效 */ .actionSheet:has([data-id="aspectratio"]):has([data-id="playbackrate"]) .actionSheetContent, .actionSheet.video-player-settings-menu .actionSheetContent { max-height: 40vh !important; overflow-y: auto !important; border-radius: 8px !important; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5) !important; min-width: 180px !important; } /* 播放器设置菜单中的弹幕设置项样式 */ [data-id="danmaku-settings"] { transition: all 0.3s ease !important; } [data-id="danmaku-settings"]:hover { background: rgba(169, 91, 194, 0.1) !important; } [data-id="danmaku-settings"] .actionSheetItemText { color: inherit !important; } /* 控制按钮容器 */ .control-buttons-container { display: flex !important; align-items: center !important; gap: 10px !important; flex-wrap: wrap !important; } /* 对话框中的控制按钮样式 */ .dialog-control-button { display: inline-flex !important; align-items: center !important; justify-content: center !important; background: rgba(255, 255, 255, 0.1) !important; border: 1px solid rgba(255, 255, 255, 0.2) !important; border-radius: 6px !important; padding: 8px 12px !important; min-width: 40px !important; height: 36px !important; cursor: pointer !important; transition: all 0.3s ease !important; } .dialog-control-button:hover { background: rgba(255, 255, 255, 0.2) !important; border: 1px solid rgba(169, 91, 194, 0.5) !important; box-shadow: 0 0 8px rgba(169, 91, 194, 0.3) !important; } .dialog-control-button .material-icons { color: #fff !important; font-size: 20px !important; } /* 自定义复选框和单选框样式 */ .danmakuSidebar input[type="checkbox"], .danmakuSidebar input[type="radio"] { -webkit-appearance: none !important; appearance: none !important; background: linear-gradient(135deg, rgba(128, 128, 128, 0.08), rgba(160, 160, 160, 0.08)) !important; border: 2px solid rgba(128, 128, 128, 0.4) !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; cursor: pointer !important; position: relative !important; backdrop-filter: blur(25px) !important; box-shadow: 0 2px 8px rgba(128, 128, 128, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } .danmakuSidebar input[type="checkbox"] { border-radius: 6px !important; width: 20px !important; height: 20px !important; } .danmakuSidebar input[type="radio"] { border-radius: 50% !important; width: 20px !important; height: 20px !important; } .danmakuSidebar input[type="checkbox"]:checked, .danmakuSidebar input[type="radio"]:checked { background: linear-gradient(135deg, #a95bc2, #00a4db) !important; border-color: rgba(169, 91, 194, 0.8) !important; box-shadow: 0 2px 12px rgba(169, 91, 194, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } .danmakuSidebar input[type="checkbox"]:checked::after { content: "✓" !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; color: white !important; font-size: 12px !important; font-weight: bold !important; } .danmakuSidebar input[type="radio"]:checked::after { content: "" !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; width: 8px !important; height: 8px !important; background: white !important; border-radius: 50% !important; } .danmakuSidebar input[type="checkbox"]:hover:not(:checked), .danmakuSidebar input[type="radio"]:hover:not(:checked) { border: 2px solid rgba(169, 91, 194, 0.6) !important; background: linear-gradient(135deg, rgba(169, 91, 194, 0.12), rgba(0, 164, 219, 0.12)) !important; box-shadow: 0 4px 15px rgba(169, 91, 194, 0.2), inset 0 1px 2px rgba(255, 255, 255, 0.12), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } /* 现代化开关样式 */ .modern-switch { position: relative !important; display: inline-block !important; width: 44px !important; height: 24px !important; padding: 0 !important; margin: 0 !important; background: transparent !important; border: none !important; cursor: pointer !important; } .modern-switch input { opacity: 0 !important; width: 0 !important; height: 0 !important; position: absolute !important; margin: 0 !important; } .modern-slider { position: absolute !important; cursor: pointer !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; background: rgba(255, 255, 255, 0.2) !important; border-radius: 24px !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; border: 1px solid rgba(255, 255, 255, 0.1) !important; width: 44px !important; height: 24px !important; } .modern-slider:before { position: absolute !important; content: "" !important; height: 18px !important; width: 18px !important; left: 2px !important; bottom: 2px !important; background: white !important; border-radius: 50% !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2) !important; } .modern-switch input:checked + .modern-slider { background: linear-gradient(135deg, #a95bc2, #00a4db) !important; border-color: transparent !important; } .modern-switch input:checked + .modern-slider:before { transform: translateX(20px) !important; box-shadow: 0 1px 4px rgba(169, 91, 194, 0.3) !important; } .modern-slider:hover { box-shadow: 0 0 8px rgba(169, 91, 194, 0.2) !important; } .modern-switch input:checked + .modern-slider:hover { box-shadow: 0 0 8px rgba(169, 91, 194, 0.4) !important; } /* 控制卡片样式 */ .control-card { transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; } .control-card:hover { transform: translateY(-2px) !important; } /* 苹果风格开关样式 */ .log-switch-container { display: flex !important; align-items: center; margin-left: 15px; } .log-switch-label { margin-right: 10px; font-size: 14px; color: #fff; } .apple-switch { position: relative; display: inline-block; width: 50px; height: 28px; } .apple-switch input { opacity: 0; width: 0; height: 0; } .apple-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background: #ccc; border-radius: 28px; transition: all 0.3s ease; } .apple-slider:before { position: absolute; content: ""; height: 22px; width: 22px; left: 3px; bottom: 3px; background: white; border-radius: 50%; transition: all 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } .apple-switch input:checked + .apple-slider { background: linear-gradient(130deg, #a95bc2, #00a4db); } .apple-switch input:checked + .apple-slider:before { transform: translateX(22px); } .apple-slider:hover { box-shadow: 0 0 8px rgba(169, 91, 194, 0.3); } .apple-switch input:checked + .apple-slider:hover { box-shadow: 0 0 8px rgba(169, 91, 194, 0.5); } /* 输入范围滑块简洁样式 */ #danmakuModal input[type="range"] { -webkit-appearance: none; appearance: none; height: 4px; border-radius: 2px; outline: none; background: linear-gradient(130deg, #a95bc2, #00a4db) !important; } #danmakuModal input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border-radius: 50%; background: linear-gradient(130deg, #a95bc2, #00a4db); cursor: pointer; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } #danmakuModal input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: linear-gradient(130deg, #a95bc2, #00a4db); cursor: pointer; border: none; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } #danmakuModal input[type="range"]::-moz-range-track { background: linear-gradient(130deg, #a95bc2, #00a4db) !important; height: 4px; border-radius: 2px; } /* 现代化弹幕输入框样式 - 增强版 */ #danmakuFontFamily, #danmakuOffsetTime, #danmakuFontOptions, #danmakuModal #danmakuOffsetTime, #danmakuModal #danmakuFontFamily, #danmakuModal #danmakuFontOptions, #danmakuModal input[type="text"], #danmakuModal input[type="number"] { background: linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08)) !important; border: 2px solid rgba(169, 91, 194, 0.4) !important; border-radius: 12px !important; padding: 10px 16px !important; color: #fff !important; font-size: 14px !important; font-weight: 500 !important; transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1) !important; backdrop-filter: blur(25px) !important; min-width: 120px !important; max-width: 100% !important; width: 100% !important; box-sizing: border-box !important; flex: 1 1 auto !important; flex-grow: 1 !important; min-height: 40px !important; height: 40px !important; line-height: 1.4 !important; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } #danmakuFontFamily:focus, #danmakuOffsetTime:focus, #danmakuFontOptions:focus, #danmakuModal #danmakuOffsetTime:focus, #danmakuModal #danmakuFontFamily:focus, #danmakuModal #danmakuFontOptions:focus, #danmakuModal input[type="text"]:focus, #danmakuModal input[type="number"]:focus { background: linear-gradient(135deg, rgba(169, 91, 194, 0.18), rgba(0, 164, 219, 0.18)) !important; border-color: rgba(169, 91, 194, 0.8) !important; box-shadow: 0 0 0 5px rgba(169, 91, 194, 0.2), 0 6px 25px rgba(169, 91, 194, 0.35), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; outline: none !important; transform: translateY(-1px) scale(1.01) !important; animation: input-focus-pulse 1.5s ease-out !important; } #danmakuFontFamily:hover:not(:focus), #danmakuOffsetTime:hover:not(:focus), #danmakuFontOptions:hover:not(:focus), #danmakuModal #danmakuOffsetTime:hover:not(:focus), #danmakuModal #danmakuFontFamily:hover:not(:focus), #danmakuModal #danmakuFontOptions:hover:not(:focus), #danmakuModal input[type="text"]:hover:not(:focus), #danmakuModal input[type="number"]:hover:not(:focus) { background: linear-gradient(135deg, rgba(169, 91, 194, 0.12), rgba(0, 164, 219, 0.12)) !important; border: 2px solid rgba(169, 91, 194, 0.6) !important; box-shadow: 0 4px 15px rgba(169, 91, 194, 0.2), inset 0 1px 2px rgba(255, 255, 255, 0.15), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; transform: translateY(-0.5px) scale(1.005) !important; } #danmakuFontFamily::placeholder, #danmakuOffsetTime::placeholder, #danmakuFontOptions::placeholder, #danmakuModal #danmakuOffsetTime::placeholder, #danmakuModal #danmakuFontFamily::placeholder, #danmakuModal #danmakuFontOptions::placeholder, #danmakuModal input[type="text"]::placeholder, #danmakuModal input[type="number"]::placeholder { color: rgba(255, 255, 255, 0.5) !important; font-weight: 400 !important; transition: color 0.3s ease !important; } #danmakuFontFamily:focus::placeholder, #danmakuOffsetTime:focus::placeholder, #danmakuFontOptions:focus::placeholder, #danmakuModal #danmakuOffsetTime:focus::placeholder, #danmakuModal #danmakuFontFamily:focus::placeholder, #danmakuModal #danmakuFontOptions:focus::placeholder, #danmakuModal input[type="text"]:focus::placeholder, #danmakuModal input[type="number"]:focus::placeholder { color: rgba(255, 255, 255, 0.7) !important; } /* 响应式设计优化 */ @media (max-width: 900px) { #danmakuModal .dialog { width: 95% !important; min-width: unset !important; } #danmakuModal div[style*="grid-template-columns"] { grid-template-columns: 1fr !important; gap: 15px !important; } } @media (max-width: 600px) { #danmakuModal .dialog { padding: 10px !important; } .control-buttons-container { flex-direction: column !important; align-items: stretch !important; } } /* 横屏手机优化 */ @media screen and (max-height: 600px) and (orientation: landscape) { #danmakuModal .dialog { width: 98% !important; max-width: none !important; height: 95vh !important; padding: 8px !important; } #danmakuModal div[style*="grid-template-columns"] { grid-template-columns: 1fr 1fr 1fr !important; gap: 8px 20px !important; } } /* 分组标题折叠样式 */ .group-title:hover { background: linear-gradient(90deg, rgba(169, 91, 194, 0.25), rgba(0, 164, 219, 0.25)) !important; } .group-title[data-collapsed="true"] { background: linear-gradient(90deg, rgba(169, 91, 194, 0.15), rgba(0, 164, 219, 0.15)) !important; } /* 控制项样式 */ .control-item, .control-card { transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; } .control-item:hover, .control-card:hover { transform: translateY(-2px) !important; } /* 按钮hover效果 */ #danmakuModal button, #danmakuModal [data-role="button"] { transition: all 0.3s ease !important; } #danmakuModal button:hover, #danmakuModal [data-role="button"]:hover { background: linear-gradient(135deg, rgba(169, 91, 194, 0.2), rgba(0, 164, 219, 0.2)) !important; border: 2px solid rgba(169, 91, 194, 0.5) !important; box-shadow: 0 4px 12px rgba(169, 91, 194, 0.3) !important; transform: translateY(-1px) !important; } /* 复选框横向排列样式优化 - 复选框左对齐,标签右对齐 */ #danmakuModal input[type="checkbox"] + label, #danmakuModal input[type="radio"] + label { margin-left: auto !important; margin-right: 0 !important; margin-bottom: 0 !important; text-align: right !important; } /* Modal中的复选框和单选框样式统一 */ #danmakuModal input[type="checkbox"], #danmakuModal input[type="radio"] { -webkit-appearance: none !important; appearance: none !important; background: linear-gradient(135deg, rgba(128, 128, 128, 0.08), rgba(160, 160, 160, 0.08)) !important; border: 2px solid rgba(128, 128, 128, 0.4) !important; border-radius: 6px !important; width: 18px !important; height: 18px !important; cursor: pointer !important; position: relative !important; backdrop-filter: blur(25px) !important; margin-right: auto !important; margin-left: 0 !important; flex-shrink: 0 !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; box-shadow: 0 2px 8px rgba(128, 128, 128, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } #danmakuModal input[type="radio"] { border-radius: 50% !important; } #danmakuModal input[type="checkbox"]:checked, #danmakuModal input[type="radio"]:checked { background: linear-gradient(135deg, #a95bc2, #00a4db) !important; border: 2px solid rgba(169, 91, 194, 0.8) !important; box-shadow: 0 2px 12px rgba(169, 91, 194, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } #danmakuModal input[type="checkbox"]:hover:not(:checked), #danmakuModal input[type="radio"]:hover:not(:checked) { border: 2px solid rgba(169, 91, 194, 0.6) !important; background: linear-gradient(135deg, rgba(169, 91, 194, 0.12), rgba(0, 164, 219, 0.12)) !important; box-shadow: 0 4px 15px rgba(169, 91, 194, 0.2), inset 0 1px 2px rgba(255, 255, 255, 0.12), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } /* 复选框容器左对齐 */ #danmakuModal div[style*="justify-content: flex-end"] { justify-content: flex-start !important; } /* 复选框父元素内部布局 */ #danmakuModal input[type="checkbox"]:parent, #danmakuModal input[type="radio"]:parent { justify-content: space-between !important; } /* 确保复选框和标签在父容器中正确对齐 */ #danmakuModal label:has(input[type="checkbox"]), #danmakuModal label:has(input[type="radio"]) { display: flex !important; align-items: center !important; justify-content: space-between !important; } /* 强制样式覆盖 - 确保所有danmaku相关输入框都使用新样式 */ input#danmakuFontFamily, input#danmakuOffsetTime, input#danmakuFontOptions, [id*="danmaku"] input[type="text"], [id*="danmaku"] input[type="number"] { background: linear-gradient(135deg, rgba(169, 91, 194, 0.08), rgba(0, 164, 219, 0.08)) !important; border: 2px solid rgba(169, 91, 194, 0.3) !important; border-radius: 12px !important; padding: 10px 16px !important; color: #fff !important; font-size: 14px !important; font-weight: 500 !important; min-height: 40px !important; line-height: 1.6 !important; backdrop-filter: blur(25px) !important; box-sizing: border-box !important; max-width: 100% !important; box-shadow: 0 2px 8px rgba(169, 91, 194, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; } input#danmakuFontFamily:focus, input#danmakuOffsetTime:focus, input#danmakuFontOptions:focus { background: linear-gradient(135deg, rgba(169, 91, 194, 0.18), rgba(0, 164, 219, 0.18)) !important; border-color: rgba(169, 91, 194, 0.8) !important; box-shadow: 0 0 0 5px rgba(169, 91, 194, 0.2), 0 6px 25px rgba(169, 91, 194, 0.35), inset 0 1px 2px rgba(255, 255, 255, 0.2), inset 0 -1px 1px rgba(0, 0, 0, 0.05) !important; outline: none !important; transform: translateY(-1px) scale(1.01) !important; } /* 复选框标签文本右对齐 */ #danmakuModal label span, #danmakuModal label:not(:has(input)) { text-align: right !important; margin-left: auto !important; } /* 响应式设计 - 控制功能弹性布局 */ @media (max-width: 900px) { .control-card { flex: 1 1 calc(50% - 12px) !important; min-width: 260px !important; } } @media (max-width: 600px) { .control-card { flex: 1 1 100% !important; min-width: 100% !important; } /* 弹幕设置对话框移动端适配 */ #danmakuModal .dialogContainer { width: 95% !important; margin: 20px auto !important; max-height: calc(100vh - 40px) !important; } /* 设置项在移动端堆叠布局 */ .setting-row { flex-direction: column !important; align-items: flex-start !important; gap: 8px !important; } .setting-row label { min-width: auto !important; margin-right: 0 !important; } } `; document.head.appendChild(style); console.log('[Danmaku Settings] 弹幕设置界面侧边栏脚本已加载'); })();