支持自定义tmdb图片baseurl

This commit is contained in:
mtvpls
2026-01-17 20:26:09 +08:00
parent be8373de40
commit 837e862d75
5 changed files with 59 additions and 10 deletions

View File

@@ -4,6 +4,7 @@ import { X, Calendar, Star, Clock, Tag, Users, Globe, Film } from 'lucide-react'
import Image from 'next/image';
import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { getTMDBImageUrl } from '@/lib/tmdb.client';
interface DetailPanelProps {
isOpen: boolean;
@@ -372,7 +373,7 @@ const DetailPanel: React.FC<DetailPanelProps> = ({
? detailResult.release_date?.substring(0, 4)
: detailResult.first_air_date?.substring(0, 4),
poster: detailResult.poster_path
? `https://image.tmdb.org/t/p/w500${detailResult.poster_path}`
? getTMDBImageUrl(detailResult.poster_path, 'w500')
: poster,
rating: detailResult.vote_average
? {
@@ -480,7 +481,7 @@ const DetailPanel: React.FC<DetailPanelProps> = ({
...prev,
title: episodesData.name || season?.name || prev.title,
intro: episodesData.overview || season?.overview || prev.overview,
poster: season?.poster_path ? `https://image.tmdb.org/t/p/w500${season.poster_path}` : prev.poster,
poster: season?.poster_path ? getTMDBImageUrl(season.poster_path, 'w500') : prev.poster,
releaseDate: episodesData.air_date || season?.air_date || prev.releaseDate,
year: episodesData.air_date?.substring(0, 4) || season?.air_date?.substring(0, 4) || prev.year,
episodesCount: episodesData.episodes?.length || season?.episode_count || prev.episodesCount,
@@ -732,7 +733,7 @@ const DetailPanel: React.FC<DetailPanelProps> = ({
{season.poster_path && (
<div className="relative w-12 h-16 rounded overflow-hidden bg-gray-200 dark:bg-gray-700 flex-shrink-0">
<Image
src={`https://image.tmdb.org/t/p/w92${season.poster_path}`}
src={getTMDBImageUrl(season.poster_path, 'w92')}
alt={season.name}
fill
className="object-cover"
@@ -771,7 +772,7 @@ const DetailPanel: React.FC<DetailPanelProps> = ({
{episode.still_path && (
<div className="relative w-full h-36 rounded overflow-hidden bg-gray-200 dark:bg-gray-700 mb-2">
<Image
src={`https://image.tmdb.org/t/p/w300${episode.still_path}`}
src={getTMDBImageUrl(episode.still_path, 'w300')}
alt={episode.name}
fill
className="object-cover"

View File

@@ -119,6 +119,9 @@ export const UserMenu: React.FC = () => {
// 折叠面板状态
const [isDoubanSectionOpen, setIsDoubanSectionOpen] = useState(true);
// TMDB 图片设置
const [tmdbImageBaseUrl, setTmdbImageBaseUrl] = useState('https://image.tmdb.org');
const [isUsageSectionOpen, setIsUsageSectionOpen] = useState(false);
const [isBufferSectionOpen, setIsBufferSectionOpen] = useState(false);
const [isDanmakuSectionOpen, setIsDanmakuSectionOpen] = useState(false);
@@ -339,6 +342,11 @@ export const UserMenu: React.FC = () => {
setDoubanImageProxyUrl(defaultDoubanImageProxyUrl);
}
const savedTmdbImageBaseUrl = localStorage.getItem('tmdbImageBaseUrl');
if (savedTmdbImageBaseUrl !== null) {
setTmdbImageBaseUrl(savedTmdbImageBaseUrl);
}
const savedEnableOptimization =
localStorage.getItem('enableOptimization');
if (savedEnableOptimization !== null) {
@@ -704,6 +712,13 @@ export const UserMenu: React.FC = () => {
}
};
const handleTmdbImageBaseUrlChange = (value: string) => {
setTmdbImageBaseUrl(value);
if (typeof window !== 'undefined') {
localStorage.setItem('tmdbImageBaseUrl', value);
}
};
const handleBufferStrategyChange = (value: string) => {
setBufferStrategy(value);
if (typeof window !== 'undefined') {
@@ -833,6 +848,7 @@ export const UserMenu: React.FC = () => {
setDoubanDataSource(defaultDoubanProxyType);
setDoubanImageProxyType(defaultDoubanImageProxyType);
setDoubanImageProxyUrl(defaultDoubanImageProxyUrl);
setTmdbImageBaseUrl('https://image.tmdb.org');
setBufferStrategy('medium');
setNextEpisodePreCache(true);
setNextEpisodeDanmakuPreload(true);
@@ -850,6 +866,7 @@ export const UserMenu: React.FC = () => {
localStorage.setItem('doubanDataSource', defaultDoubanProxyType);
localStorage.setItem('doubanImageProxyType', defaultDoubanImageProxyType);
localStorage.setItem('doubanImageProxyUrl', defaultDoubanImageProxyUrl);
localStorage.setItem('tmdbImageBaseUrl', 'https://image.tmdb.org');
localStorage.setItem('bufferStrategy', 'medium');
localStorage.setItem('nextEpisodePreCache', 'true');
localStorage.setItem('nextEpisodeDanmakuPreload', 'true');
@@ -1167,7 +1184,7 @@ export const UserMenu: React.FC = () => {
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'
>
<h3 className='text-base font-semibold text-gray-800 dark:text-gray-200'>
</h3>
{isDoubanSectionOpen ? (
<ChevronUp className='w-5 h-5 text-gray-600 dark:text-gray-400' />
@@ -1384,6 +1401,30 @@ export const UserMenu: React.FC = () => {
/>
</div>
)}
{/* 分割线 */}
<div className='border-t border-gray-200 dark:border-gray-700'></div>
{/* TMDB 图片网络请求地址设置 */}
<div className='space-y-3'>
<div>
<h4 className='text-sm font-medium text-gray-700 dark:text-gray-300'>
TMDB
</h4>
<p className='text-xs text-gray-500 dark:text-gray-400 mt-1'>
TMDB Base URL默认: https://image.tmdb.org
</p>
</div>
<input
type='text'
className='w-full px-3 py-2.5 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 placeholder-gray-500 dark:placeholder-gray-400 shadow-sm hover:border-gray-400 dark:hover:border-gray-500'
placeholder='例如: https://image.tmdb.org'
value={tmdbImageBaseUrl}
onChange={(e) =>
handleTmdbImageBaseUrlChange(e.target.value)
}
/>
</div>
</div>
)}
</div>