进度条图标自定义
This commit is contained in:
BIN
public/icons/q/renako.png
Normal file
BIN
public/icons/q/renako.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
@@ -6268,6 +6268,9 @@ const ThemeConfigComponent = ({
|
||||
customCSS: '',
|
||||
enableCache: true,
|
||||
cacheMinutes: 1440, // 默认1天(1440分钟)
|
||||
progressThumbType: 'default' as 'default' | 'preset' | 'custom',
|
||||
progressThumbPresetId: '',
|
||||
progressThumbCustomUrl: '',
|
||||
});
|
||||
const [loginBackgroundImages, setLoginBackgroundImages] = useState<string[]>(['']);
|
||||
const [registerBackgroundImages, setRegisterBackgroundImages] = useState<string[]>(['']);
|
||||
@@ -6280,6 +6283,9 @@ const ThemeConfigComponent = ({
|
||||
customCSS: config.ThemeConfig.customCSS || '',
|
||||
enableCache: config.ThemeConfig.enableCache !== false,
|
||||
cacheMinutes: config.ThemeConfig.cacheMinutes || 1440,
|
||||
progressThumbType: config.ThemeConfig.progressThumbType || 'default',
|
||||
progressThumbPresetId: config.ThemeConfig.progressThumbPresetId || '',
|
||||
progressThumbCustomUrl: config.ThemeConfig.progressThumbCustomUrl || '',
|
||||
});
|
||||
|
||||
// 解析背景图配置
|
||||
@@ -6711,6 +6717,170 @@ const ThemeConfigComponent = ({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 进度条图标配置 */}
|
||||
<div className='bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700'>
|
||||
<h3 className='text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2'>
|
||||
<Palette className='w-5 h-5' />
|
||||
进度条图标
|
||||
</h3>
|
||||
<p className='text-sm text-gray-600 dark:text-gray-400 mb-4'>
|
||||
自定义视频播放器进度条的滑块图标,让播放器更具个性
|
||||
</p>
|
||||
|
||||
{/* 图标类型选择 */}
|
||||
<div className='space-y-4 mb-6'>
|
||||
<label className='flex items-center space-x-3 cursor-pointer'>
|
||||
<input
|
||||
type='radio'
|
||||
checked={themeSettings.progressThumbType === 'default'}
|
||||
onChange={() =>
|
||||
setThemeSettings((prev) => ({
|
||||
...prev,
|
||||
progressThumbType: 'default',
|
||||
}))
|
||||
}
|
||||
className='w-4 h-4 text-blue-600'
|
||||
/>
|
||||
<span className='text-gray-900 dark:text-gray-100'>
|
||||
默认圆点
|
||||
</span>
|
||||
</label>
|
||||
<label className='flex items-center space-x-3 cursor-pointer'>
|
||||
<input
|
||||
type='radio'
|
||||
checked={themeSettings.progressThumbType === 'preset'}
|
||||
onChange={() =>
|
||||
setThemeSettings((prev) => ({
|
||||
...prev,
|
||||
progressThumbType: 'preset',
|
||||
}))
|
||||
}
|
||||
className='w-4 h-4 text-blue-600'
|
||||
/>
|
||||
<span className='text-gray-900 dark:text-gray-100'>
|
||||
内置图标
|
||||
</span>
|
||||
</label>
|
||||
<label className='flex items-center space-x-3 cursor-pointer'>
|
||||
<input
|
||||
type='radio'
|
||||
checked={themeSettings.progressThumbType === 'custom'}
|
||||
onChange={() =>
|
||||
setThemeSettings((prev) => ({
|
||||
...prev,
|
||||
progressThumbType: 'custom',
|
||||
}))
|
||||
}
|
||||
className='w-4 h-4 text-blue-600'
|
||||
/>
|
||||
<span className='text-gray-900 dark:text-gray-100'>
|
||||
自定义图标
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* 预制图标选择 */}
|
||||
{themeSettings.progressThumbType === 'preset' && (
|
||||
<div className='space-y-3 mb-4'>
|
||||
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300'>
|
||||
选择内置图标
|
||||
</label>
|
||||
<div className='grid grid-cols-2 md:grid-cols-3 gap-3'>
|
||||
{[
|
||||
{ id: 'renako', name: '玲奈子', url: '/icons/q/renako.png', color: '#ec4899' },
|
||||
].map((thumb) => (
|
||||
<button
|
||||
key={thumb.id}
|
||||
type='button'
|
||||
onClick={() =>
|
||||
setThemeSettings((prev) => ({
|
||||
...prev,
|
||||
progressThumbPresetId: thumb.id,
|
||||
}))
|
||||
}
|
||||
className={`relative p-4 border-2 rounded-lg transition-all ${
|
||||
themeSettings.progressThumbPresetId === thumb.id
|
||||
? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
|
||||
: 'border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500'
|
||||
}`}
|
||||
>
|
||||
<div className='flex flex-col items-center gap-2'>
|
||||
<img
|
||||
src={thumb.url}
|
||||
alt={thumb.name}
|
||||
className='w-12 h-12 object-contain'
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).src = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="48" height="48"%3E%3Crect width="48" height="48" fill="%23ddd"/%3E%3Ctext x="50%25" y="50%25" text-anchor="middle" dy=".3em" fill="%23999"%3E?%3C/text%3E%3C/svg%3E';
|
||||
}}
|
||||
/>
|
||||
<span className='text-sm font-medium text-gray-700 dark:text-gray-300 text-center'>
|
||||
{thumb.name}
|
||||
</span>
|
||||
<div
|
||||
className='w-8 h-2 rounded-full'
|
||||
style={{ backgroundColor: thumb.color }}
|
||||
title='进度条颜色'
|
||||
/>
|
||||
</div>
|
||||
{themeSettings.progressThumbPresetId === thumb.id && (
|
||||
<div className='absolute top-2 right-2'>
|
||||
<Check className='w-5 h-5 text-blue-600 dark:text-blue-400' />
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<p className='text-xs text-gray-500 dark:text-gray-400 mt-2'>
|
||||
选择玲奈子图标时,进度条将变为粉色主题
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 自定义图标URL输入 */}
|
||||
{themeSettings.progressThumbType === 'custom' && (
|
||||
<div className='space-y-3'>
|
||||
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300'>
|
||||
自定义图标URL
|
||||
</label>
|
||||
<input
|
||||
type='text'
|
||||
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400'
|
||||
placeholder='例如: https://example.com/icon.png'
|
||||
value={themeSettings.progressThumbCustomUrl}
|
||||
onChange={(e) =>
|
||||
setThemeSettings((prev) => ({
|
||||
...prev,
|
||||
progressThumbCustomUrl: e.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
<p className='text-xs text-gray-500 dark:text-gray-400'>
|
||||
支持 PNG、JPG、GIF、WebP 格式,建议尺寸 32x32px,图片URL必须可公开访问
|
||||
</p>
|
||||
{themeSettings.progressThumbCustomUrl && (
|
||||
<div className='mt-2 p-3 bg-gray-50 dark:bg-gray-700 rounded-lg'>
|
||||
<p className='text-xs text-gray-600 dark:text-gray-400 mb-2'>预览:</p>
|
||||
<img
|
||||
src={themeSettings.progressThumbCustomUrl}
|
||||
alt='自定义图标预览'
|
||||
className='w-12 h-12 object-contain border border-gray-300 dark:border-gray-600 rounded'
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
const parent = (e.target as HTMLImageElement).parentElement;
|
||||
if (parent && !parent.querySelector('.error-msg')) {
|
||||
const errorMsg = document.createElement('p');
|
||||
errorMsg.className = 'text-xs text-red-500 error-msg';
|
||||
errorMsg.textContent = '图片加载失败,请检查URL是否正确';
|
||||
parent.appendChild(errorMsg);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 保存按钮 */}
|
||||
<div className='flex justify-end'>
|
||||
<button
|
||||
|
||||
@@ -36,6 +36,9 @@ export async function POST(request: NextRequest) {
|
||||
cacheMinutes,
|
||||
loginBackgroundImage,
|
||||
registerBackgroundImage,
|
||||
progressThumbType,
|
||||
progressThumbPresetId,
|
||||
progressThumbCustomUrl,
|
||||
} = body as {
|
||||
enableBuiltInTheme: boolean;
|
||||
builtInTheme: string;
|
||||
@@ -44,6 +47,9 @@ export async function POST(request: NextRequest) {
|
||||
cacheMinutes: number;
|
||||
loginBackgroundImage?: string;
|
||||
registerBackgroundImage?: string;
|
||||
progressThumbType?: 'default' | 'preset' | 'custom';
|
||||
progressThumbPresetId?: string;
|
||||
progressThumbCustomUrl?: string;
|
||||
};
|
||||
|
||||
// 参数校验
|
||||
@@ -118,6 +124,9 @@ export async function POST(request: NextRequest) {
|
||||
cacheVersion: cssChanged ? currentVersion + 1 : currentVersion,
|
||||
loginBackgroundImage: loginBackgroundImage?.trim() || undefined,
|
||||
registerBackgroundImage: registerBackgroundImage?.trim() || undefined,
|
||||
progressThumbType: progressThumbType || 'default',
|
||||
progressThumbPresetId: progressThumbPresetId?.trim() || undefined,
|
||||
progressThumbCustomUrl: progressThumbCustomUrl?.trim() || undefined,
|
||||
};
|
||||
|
||||
// 写入数据库
|
||||
|
||||
@@ -50,6 +50,9 @@ export async function GET(request: NextRequest) {
|
||||
OIDCButtonText: config.SiteConfig.OIDCButtonText || '',
|
||||
loginBackgroundImage: config.ThemeConfig?.loginBackgroundImage || '',
|
||||
registerBackgroundImage: config.ThemeConfig?.registerBackgroundImage || '',
|
||||
progressThumbType: config.ThemeConfig?.progressThumbType || 'default',
|
||||
progressThumbPresetId: config.ThemeConfig?.progressThumbPresetId || '',
|
||||
progressThumbCustomUrl: config.ThemeConfig?.progressThumbCustomUrl || '',
|
||||
// AI配置(只暴露功能开关,不暴露API密钥等敏感信息)
|
||||
AIEnabled: config.AIConfig?.Enabled || false,
|
||||
AIEnableHomepageEntry: config.AIConfig?.EnableHomepageEntry || false,
|
||||
|
||||
@@ -70,6 +70,9 @@ export default async function RootLayout({
|
||||
let xiaoyaEnabled = false;
|
||||
let loginBackgroundImage = '';
|
||||
let registerBackgroundImage = '';
|
||||
let progressThumbType = 'default';
|
||||
let progressThumbPresetId = '';
|
||||
let progressThumbCustomUrl = '';
|
||||
let enableRegistration = false;
|
||||
let loginRequireTurnstile = false;
|
||||
let registrationRequireTurnstile = false;
|
||||
@@ -115,6 +118,9 @@ export default async function RootLayout({
|
||||
tmdbApiKey = config.SiteConfig.TMDBApiKey || '';
|
||||
loginBackgroundImage = config.ThemeConfig?.loginBackgroundImage || '';
|
||||
registerBackgroundImage = config.ThemeConfig?.registerBackgroundImage || '';
|
||||
progressThumbType = config.ThemeConfig?.progressThumbType || 'default';
|
||||
progressThumbPresetId = config.ThemeConfig?.progressThumbPresetId || '';
|
||||
progressThumbCustomUrl = config.ThemeConfig?.progressThumbCustomUrl || '';
|
||||
enableRegistration = config.SiteConfig.EnableRegistration || false;
|
||||
loginRequireTurnstile = config.SiteConfig.LoginRequireTurnstile || false;
|
||||
registrationRequireTurnstile = config.SiteConfig.RegistrationRequireTurnstile || false;
|
||||
@@ -178,6 +184,9 @@ export default async function RootLayout({
|
||||
PRIVATE_LIBRARY_ENABLED: openListEnabled || embyEnabled || xiaoyaEnabled,
|
||||
LOGIN_BACKGROUND_IMAGE: loginBackgroundImage,
|
||||
REGISTER_BACKGROUND_IMAGE: registerBackgroundImage,
|
||||
PROGRESS_THUMB_TYPE: progressThumbType,
|
||||
PROGRESS_THUMB_PRESET_ID: progressThumbPresetId,
|
||||
PROGRESS_THUMB_CUSTOM_URL: progressThumbCustomUrl,
|
||||
ENABLE_REGISTRATION: enableRegistration,
|
||||
LOGIN_REQUIRE_TURNSTILE: loginRequireTurnstile,
|
||||
REGISTRATION_REQUIRE_TURNSTILE: registrationRequireTurnstile,
|
||||
|
||||
@@ -5812,6 +5812,83 @@ function PlayPageClient() {
|
||||
setPlayerReady(true);
|
||||
console.log('[PlayPage] Player ready, triggering sync setup');
|
||||
|
||||
// 应用进度条图标配置 - 尽早执行
|
||||
const applyProgressThumbConfig = () => {
|
||||
try {
|
||||
const config = (window as any).RUNTIME_CONFIG;
|
||||
|
||||
if (!config || config.PROGRESS_THUMB_TYPE === 'default') {
|
||||
// 使用默认样式,移除自定义样式
|
||||
const oldStyle = document.getElementById('custom-progress-thumb-style');
|
||||
if (oldStyle) oldStyle.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
let thumbUrl = '';
|
||||
let thumbColor = '#22c55e'; // 默认绿色
|
||||
|
||||
if (config.PROGRESS_THUMB_TYPE === 'preset' && config.PROGRESS_THUMB_PRESET_ID) {
|
||||
const presetConfig: Record<string, { url: string; color: string }> = {
|
||||
renako: { url: '/icons/q/renako.png', color: '#ec4899' }, // 粉色
|
||||
};
|
||||
const preset = presetConfig[config.PROGRESS_THUMB_PRESET_ID];
|
||||
if (preset) {
|
||||
thumbUrl = preset.url;
|
||||
thumbColor = preset.color;
|
||||
}
|
||||
} else if (config.PROGRESS_THUMB_TYPE === 'custom' && config.PROGRESS_THUMB_CUSTOM_URL) {
|
||||
thumbUrl = config.PROGRESS_THUMB_CUSTOM_URL;
|
||||
}
|
||||
|
||||
// 修改 ArtPlayer 的主题色
|
||||
if (artPlayerRef.current) {
|
||||
artPlayerRef.current.theme = thumbColor;
|
||||
}
|
||||
|
||||
if (thumbUrl) {
|
||||
// 根据预设ID确定尺寸
|
||||
let width = '30px';
|
||||
let height = '30px';
|
||||
let marginLeft = '-15px';
|
||||
|
||||
// renako 图标特殊处理(288x404比例,放大1.25倍)
|
||||
if (config.PROGRESS_THUMB_TYPE === 'preset' && config.PROGRESS_THUMB_PRESET_ID === 'renako') {
|
||||
width = '26.875px'; // 21.5 * 1.25
|
||||
height = '37.5px'; // 30 * 1.25
|
||||
marginLeft = '-13.4375px'; // 10.75 * 1.25
|
||||
}
|
||||
|
||||
// 动态设置背景图片
|
||||
const style = document.createElement('style');
|
||||
style.id = 'custom-progress-thumb-style';
|
||||
style.textContent = `
|
||||
/* 替换默认的进度条圆点为自定义图标 */
|
||||
.art-video-player .art-progress-indicator {
|
||||
width: ${width} !important;
|
||||
height: ${height} !important;
|
||||
background-image: url('${thumbUrl}') !important;
|
||||
background-size: contain !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: center !important;
|
||||
background-color: transparent !important;
|
||||
border-radius: 0 !important;
|
||||
margin-left: ${marginLeft} !important;
|
||||
}
|
||||
`;
|
||||
|
||||
// 移除旧样式
|
||||
const oldStyle = document.getElementById('custom-progress-thumb-style');
|
||||
if (oldStyle) oldStyle.remove();
|
||||
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[进度条图标] 应用配置失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
applyProgressThumbConfig();
|
||||
|
||||
// 添加字幕切换功能
|
||||
const currentSubtitles = detailRef.current?.subtitles?.[currentEpisodeIndex] || [];
|
||||
if (currentSubtitles.length > 0 && artPlayerRef.current) {
|
||||
@@ -6031,7 +6108,7 @@ function PlayPageClient() {
|
||||
saveDanmakuDisplayState(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 播放器就绪后,如果正在播放则请求 Wake Lock
|
||||
|
||||
@@ -115,6 +115,10 @@ export interface AdminConfig {
|
||||
cacheVersion: number; // CSS版本号(用于缓存控制)
|
||||
loginBackgroundImage?: string; // 登录界面背景图
|
||||
registerBackgroundImage?: string; // 注册界面背景图
|
||||
// 进度条图标配置
|
||||
progressThumbType?: 'default' | 'preset' | 'custom'; // 图标类型
|
||||
progressThumbPresetId?: string; // 预制图标ID
|
||||
progressThumbCustomUrl?: string; // 自定义图标URL
|
||||
};
|
||||
OpenListConfig?: {
|
||||
Enabled: boolean; // 是否启用私人影库功能
|
||||
|
||||
Reference in New Issue
Block a user