diff --git a/src/components/UserMenu.tsx b/src/components/UserMenu.tsx
index 8cdb115..3dbf8a8 100644
--- a/src/components/UserMenu.tsx
+++ b/src/components/UserMenu.tsx
@@ -6,6 +6,7 @@ import {
Bell,
Check,
ChevronDown,
+ ChevronUp,
Copy,
Download,
ExternalLink,
@@ -101,6 +102,12 @@ export const UserMenu: React.FC = () => {
const [nextEpisodePreCache, setNextEpisodePreCache] = useState(true);
const [isBufferStrategyDropdownOpen, setIsBufferStrategyDropdownOpen] = useState(false);
+ // 折叠面板状态
+ const [isDoubanSectionOpen, setIsDoubanSectionOpen] = useState(true);
+ const [isUsageSectionOpen, setIsUsageSectionOpen] = useState(false);
+ const [isBufferSectionOpen, setIsBufferSectionOpen] = useState(false);
+ const [isDanmakuSectionOpen, setIsDanmakuSectionOpen] = useState(false);
+
// 豆瓣数据源选项
const doubanDataSourceOptions = [
{ value: 'direct', label: '直连(服务器直接请求豆瓣)' },
@@ -912,7 +919,7 @@ export const UserMenu: React.FC = () => {
>
{/* 内容容器 - 独立的滚动区域 */}
{
{/* 设置项 */}
-
- {/* 豆瓣数据源选择 */}
-
-
-
- 豆瓣数据代理
-
-
- 选择获取豆瓣数据的方式
-
-
-
- {/* 自定义下拉选择框 */}
-
-
- {/* 下拉箭头 */}
-
-
-
-
- {/* 下拉选项列表 */}
- {isDoubanDropdownOpen && (
-
- {doubanDataSourceOptions.map((option) => (
-
- ))}
-
+
+ {/* 豆瓣设置 */}
+
+
-
- {/* 感谢信息 */}
- {getThanksInfo(doubanDataSource) && (
-
-
-
- )}
-
-
- {/* 豆瓣代理地址设置 - 仅在选择自定义代理时显示 */}
- {doubanDataSource === 'custom' && (
-
-
-
- 豆瓣代理地址
-
-
- 自定义代理服务器地址
-
-
-
handleDoubanProxyUrlChange(e.target.value)}
- />
-
- )}
-
- {/* 分割线 */}
-
-
- {/* 豆瓣图片代理设置 */}
-
-
-
- 豆瓣图片代理
-
-
- 选择获取豆瓣图片的方式
-
-
-
- {/* 自定义下拉选择框 */}
-
-
- {/* 下拉箭头 */}
-
-
-
-
- {/* 下拉选项列表 */}
- {isDoubanImageProxyDropdownOpen && (
-
- {doubanImageProxyTypeOptions.map((option) => (
+
+ {isDoubanSectionOpen && (
+
+ {/* 豆瓣数据源选择 */}
+
+
+
+ 豆瓣数据代理
+
+
+ 选择获取豆瓣数据的方式
+
+
+
+ {/* 自定义下拉选择框 */}
- ))}
-
- )}
-
- {/* 感谢信息 */}
- {getThanksInfo(doubanImageProxyType) && (
-
-
-
- )}
-
-
- {/* 豆瓣图片代理地址设置 - 仅在选择自定义代理时显示 */}
- {doubanImageProxyType === 'custom' && (
-
-
-
- 豆瓣图片代理地址
-
-
- 自定义图片代理服务器地址
-
-
-
- handleDoubanImageProxyUrlChange(e.target.value)
- }
- />
-
- )}
-
- {/* 分割线 */}
-
-
- {/* 默认聚合搜索结果 */}
-
-
-
- 默认聚合搜索结果
-
-
- 搜索时默认按标题和年份聚合显示结果
-
-
-
-
-
- {/* 优选和测速 */}
-
-
-
- 优选和测速
-
-
- 如出现播放器劫持问题可关闭
-
-
-
-
-
- {/* 流式搜索 */}
-
-
-
- 流式搜索输出
-
-
- 启用搜索结果实时流式输出,关闭后使用传统一次性搜索
-
-
-
-
-
- {/* 直播视频浏览器直连 */}
-
-
-
- IPTV 视频浏览器直连
-
-
- 开启 IPTV 视频浏览器直连时,需要自备 Allow CORS 插件
-
-
-
-
-
- {/* 禁用弹幕热力 */}
- {/* 禁用背景图渲染 */}
-
-
-
- 禁用背景图渲染
-
-
- 关闭播放页面的TMDB背景图显示(需手动刷新页面生效)
-
-
-
-
-
- {/* 启用预告片 */}
-
-
-
- 首页预告片
-
-
- 在首页轮播图中显示视频预告片(需刷新页面生效)
-
-
-
-
-
- {/* 分割线 */}
-
-
- {/* 缓冲设置 */}
-
-
-
- 缓冲设置
-
-
- 调整播放器缓冲策略(仅在播放页面生效)
-
-
-
- {/* 缓冲策略 */}
-
-
-
- 缓冲策略
-
-
- 设置视频缓冲块大小,影响播放流畅度和流量消耗
-
-
-
- {/* 自定义下拉选择框 */}
-
-
- {/* 下拉箭头 */}
-
-
-
-
- {/* 下拉选项列表 */}
- {isBufferStrategyDropdownOpen && (
-
- {bufferStrategyOptions.map((option) => (
-
+
+ {/* 感谢信息 */}
+ {getThanksInfo(doubanDataSource) && (
+
+
+ window.open(getThanksInfo(doubanDataSource)!.url, '_blank')
+ }
+ className='flex items-center justify-center gap-1.5 w-full px-3 text-xs text-gray-500 dark:text-gray-400 cursor-pointer'
>
- {option.label}
- {bufferStrategy === option.value && (
-
- )}
+
+ {getThanksInfo(doubanDataSource)!.text}
+
+
- ))}
+
+ )}
+
+
+ {/* 豆瓣代理地址设置 - 仅在选择自定义代理时显示 */}
+ {doubanDataSource === 'custom' && (
+
+
+
+ 豆瓣代理地址
+
+
+ 自定义代理服务器地址
+
+
+
handleDoubanProxyUrlChange(e.target.value)}
+ />
+
+ )}
+
+ {/* 分割线 */}
+
+
+ {/* 豆瓣图片代理设置 */}
+
+
+
+ 豆瓣图片代理
+
+
+ 选择获取豆瓣图片的方式
+
+
+
+ {/* 自定义下拉选择框 */}
+
+ setIsDoubanImageProxyDropdownOpen(
+ !isDoubanImageProxyDropdownOpen
+ )
+ }
+ className='w-full px-3 py-2.5 pr-10 border border-gray-300 dark:border-gray-600 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-all duration-200 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm hover:border-gray-400 dark:hover:border-gray-500 text-left'
+ >
+ {
+ doubanImageProxyTypeOptions.find(
+ (option) => option.value === doubanImageProxyType
+ )?.label
+ }
+
+
+ {/* 下拉箭头 */}
+
+
+
+
+ {/* 下拉选项列表 */}
+ {isDoubanImageProxyDropdownOpen && (
+
+ {doubanImageProxyTypeOptions.map((option) => (
+ {
+ handleDoubanImageProxyTypeChange(option.value);
+ setIsDoubanImageProxyDropdownOpen(false);
+ }}
+ className={`w-full px-3 py-2.5 text-left text-sm transition-colors duration-150 flex items-center justify-between hover:bg-gray-100 dark:hover:bg-gray-700 ${doubanImageProxyType === option.value
+ ? 'bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-green-400'
+ : 'text-gray-900 dark:text-gray-100'
+ }`}
+ >
+ {option.label}
+ {doubanImageProxyType === option.value && (
+
+ )}
+
+ ))}
+
+ )}
+
+
+ {/* 感谢信息 */}
+ {getThanksInfo(doubanImageProxyType) && (
+
+
+ window.open(
+ getThanksInfo(doubanImageProxyType)!.url,
+ '_blank'
+ )
+ }
+ className='flex items-center justify-center gap-1.5 w-full px-3 text-xs text-gray-500 dark:text-gray-400 cursor-pointer'
+ >
+
+ {getThanksInfo(doubanImageProxyType)!.text}
+
+
+
+
+ )}
+
+
+ {/* 豆瓣图片代理地址设置 - 仅在选择自定义代理时显示 */}
+ {doubanImageProxyType === 'custom' && (
+
+
+
+ 豆瓣图片代理地址
+
+
+ 自定义图片代理服务器地址
+
+
+
+ handleDoubanImageProxyUrlChange(e.target.value)
+ }
+ />
)}
-
-
- {/* 下集预缓冲 */}
-
-
-
- 下集预缓冲
-
-
- 播放进度达到90%时,自动预缓冲下一集内容
-
-
-
-
+ )}
- {/* 分割线 */}
-
-
- {/* 清除弹幕缓存 */}
-
-
-
- 弹幕缓存管理
-
-
- 清除所有已缓存的弹幕数据
-
-
+ {/* 使用设置 */}
+
setIsUsageSectionOpen(!isUsageSectionOpen)}
+ className='w-full px-3 py-2.5 md:px-4 md:py-3 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-750 transition-colors flex items-center justify-between'
>
- {isClearingCache ? (
- <>
-
- 清除中...
- >
+
+ 使用设置
+
+ {isUsageSectionOpen ? (
+
) : (
- <>
-
- 清除弹幕缓存
- >
+
)}
+ {isUsageSectionOpen && (
+
+ {/* 默认聚合搜索结果 */}
+
+
+
+ 默认聚合搜索结果
+
+
+ 搜索时默认按标题和年份聚合显示结果
+
+
+
+
- {/* 成功/失败提示 */}
- {clearCacheMessage && (
-
- {clearCacheMessage}
+ {/* 优选和测速 */}
+
+
+
+ 优选和测速
+
+
+ 如出现播放器劫持问题可关闭
+
+
+
+
+
+ {/* 流式搜索 */}
+
+
+
+ 流式搜索输出
+
+
+ 启用搜索结果实时流式输出,关闭后使用传统一次性搜索
+
+
+
+
+
+ {/* 直播视频浏览器直连 */}
+
+
+
+ IPTV 视频浏览器直连
+
+
+ 开启 IPTV 视频浏览器直连时,需要自备 Allow CORS 插件
+
+
+
+
+
+ {/* 禁用背景图渲染 */}
+
+
+
+ 禁用背景图渲染
+
+
+ 关闭播放页面的TMDB背景图显示(需手动刷新页面生效)
+
+
+
+
+
+ {/* 启用预告片 */}
+
+
+
+ 首页预告片
+
+
+ 在首页轮播图中显示视频预告片(需刷新页面生效)
+
+
+
+
+
+ )}
+
+
+ {/* 缓冲设置 */}
+
+
setIsBufferSectionOpen(!isBufferSectionOpen)}
+ className='w-full px-3 py-2.5 md:px-4 md:py-3 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-750 transition-colors flex items-center justify-between'
+ >
+
+ 缓冲设置
+
+ {isBufferSectionOpen ? (
+
+ ) : (
+
+ )}
+
+ {isBufferSectionOpen && (
+
+
+
+ 调整播放器缓冲策略(仅在播放页面生效)
+
+
+
+ {/* 缓冲策略 */}
+
+
+
+ 缓冲策略
+
+
+ 设置视频缓冲块大小,影响播放流畅度和流量消耗
+
+
+
+ {/* 自定义下拉选择框 */}
+
setIsBufferStrategyDropdownOpen(!isBufferStrategyDropdownOpen)}
+ className='w-full px-3 py-2.5 pr-10 border border-gray-300 dark:border-gray-600 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-all duration-200 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm hover:border-gray-400 dark:hover:border-gray-500 text-left'
+ >
+ {
+ bufferStrategyOptions.find(
+ (option) => option.value === bufferStrategy
+ )?.label
+ }
+
+
+ {/* 下拉箭头 */}
+
+
+
+
+ {/* 下拉选项列表 */}
+ {isBufferStrategyDropdownOpen && (
+
+ {bufferStrategyOptions.map((option) => (
+ {
+ handleBufferStrategyChange(option.value);
+ setIsBufferStrategyDropdownOpen(false);
+ }}
+ className={`w-full px-3 py-2.5 text-left text-sm transition-colors duration-150 flex items-center justify-between hover:bg-gray-100 dark:hover:bg-gray-700 ${bufferStrategy === option.value
+ ? 'bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-green-400'
+ : 'text-gray-900 dark:text-gray-100'
+ }`}
+ >
+ {option.label}
+ {bufferStrategy === option.value && (
+
+ )}
+
+ ))}
+
+ )}
+
+
+
+ {/* 下集预缓冲 */}
+
+
+
+ 下集预缓冲
+
+
+ 播放进度达到90%时,自动预缓冲下一集内容
+
+
+
+
+
+ )}
+
+
+ {/* 弹幕设置 */}
+
+
setIsDanmakuSectionOpen(!isDanmakuSectionOpen)}
+ className='w-full px-3 py-2.5 md:px-4 md:py-3 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-750 transition-colors flex items-center justify-between'
+ >
+
+ 弹幕设置
+
+ {isDanmakuSectionOpen ? (
+
+ ) : (
+
+ )}
+
+ {isDanmakuSectionOpen && (
+
+ {/* 清除弹幕缓存 */}
+
+
+
+ 弹幕缓存管理
+
+
+ 清除所有已缓存的弹幕数据
+
+
+
+ {isClearingCache ? (
+ <>
+
+ 清除中...
+ >
+ ) : (
+ <>
+
+ 清除弹幕缓存
+ >
+ )}
+
+
+ {/* 成功/失败提示 */}
+ {clearCacheMessage && (
+
+ {clearCacheMessage}
+
+ )}
+
)}