feat: optimize search in play page

This commit is contained in:
shinya
2025-07-20 18:06:14 +08:00
parent bcdac905b5
commit 1490c0614b
5 changed files with 40 additions and 22 deletions

View File

@@ -295,6 +295,7 @@ function DoubanPageClient() {
douban_id={item.id} douban_id={item.id}
rate={item.rate} rate={item.rate}
year={item.year} year={item.year}
type={type === 'movie' ? 'movie' : ''} // 电影类型严格控制tv 不控
/> />
</div> </div>
))} ))}

View File

@@ -190,6 +190,7 @@ function HomeClient() {
query={item.search_title} query={item.search_title}
{...item} {...item}
from='favorite' from='favorite'
type={item.episodes > 1 ? 'tv' : ''}
/> />
</div> </div>
))} ))}
@@ -247,6 +248,7 @@ function HomeClient() {
douban_id={movie.id} douban_id={movie.id}
rate={movie.rate} rate={movie.rate}
year={movie.year} year={movie.year}
type='movie'
/> />
</div> </div>
))} ))}

View File

@@ -465,6 +465,27 @@ function PlayPageClient() {
// 进入页面时直接获取全部源信息 // 进入页面时直接获取全部源信息
useEffect(() => { useEffect(() => {
const fetchSourceDetail = async (
source: string,
id: string
): Promise<SearchResult[]> => {
try {
const detailResponse = await fetch(
`/api/detail?source=${source}&id=${id}`
);
if (!detailResponse.ok) {
throw new Error('获取视频详情失败');
}
const detailData = (await detailResponse.json()) as SearchResult;
setAvailableSources([detailData]);
return [detailData];
} catch (err) {
console.error('获取视频详情失败:', err);
return [];
} finally {
setSourceSearchLoading(false);
}
};
const fetchSourcesData = async (query: string): Promise<SearchResult[]> => { const fetchSourcesData = async (query: string): Promise<SearchResult[]> => {
// 根据搜索词获取全部源信息 // 根据搜索词获取全部源信息
try { try {
@@ -489,24 +510,6 @@ function PlayPageClient() {
(searchType === 'movie' && result.episodes.length === 1) (searchType === 'movie' && result.episodes.length === 1)
: true) : true)
); );
if (results.length !== 0) {
setAvailableSources(results);
return results;
}
// 未获取到任何内容fallback 使用 source + id
if (!currentSource || !currentId) {
return [];
}
const detailResponse = await fetch(
`/api/detail?source=${currentSource}&id=${currentId}`
);
if (!detailResponse.ok) {
throw new Error('获取视频详情失败');
}
const detailData = (await detailResponse.json()) as SearchResult;
results.push(detailData);
setAvailableSources(results); setAvailableSources(results);
return results; return results;
} catch (err) { } catch (err) {
@@ -532,7 +535,16 @@ function PlayPageClient() {
: '🔍 正在搜索播放源...' : '🔍 正在搜索播放源...'
); );
const sourcesInfo = await fetchSourcesData(searchTitle || videoTitle); let sourcesInfo = await fetchSourcesData(searchTitle || videoTitle);
if (
currentSource &&
currentId &&
!sourcesInfo.some(
(source) => source.source === currentSource && source.id === currentId
)
) {
sourcesInfo = await fetchSourceDetail(currentSource, currentId);
}
if (sourcesInfo.length === 0) { if (sourcesInfo.length === 0) {
setError('未找到匹配结果'); setError('未找到匹配结果');
setLoading(false); setLoading(false);

View File

@@ -143,6 +143,7 @@ export default function ContinueWatching({ className }: ContinueWatchingProps) {
prev.filter((r) => r.key !== record.key) prev.filter((r) => r.key !== record.key)
) )
} }
type={record.total_episodes > 1 ? 'tv' : ''}
/> />
</div> </div>
); );

View File

@@ -34,6 +34,7 @@ interface VideoCardProps {
onDelete?: () => void; onDelete?: () => void;
rate?: string; rate?: string;
items?: SearchResult[]; items?: SearchResult[];
type?: string;
} }
export default function VideoCard({ export default function VideoCard({
@@ -52,6 +53,7 @@ export default function VideoCard({
onDelete, onDelete,
rate, rate,
items, items,
type = '',
}: VideoCardProps) { }: VideoCardProps) {
const router = useRouter(); const router = useRouter();
const [favorited, setFavorited] = useState(false); const [favorited, setFavorited] = useState(false);
@@ -105,10 +107,10 @@ export default function VideoCard({
const actualYear = aggregateData?.first.year ?? year; const actualYear = aggregateData?.first.year ?? year;
const actualQuery = query || ''; const actualQuery = query || '';
const actualSearchType = isAggregate const actualSearchType = isAggregate
? aggregateData?.first.episodes.length === 1 ? aggregateData?.first.episodes?.length === 1
? 'movie' ? 'movie'
: 'tv' : 'tv'
: ''; : type;
// 获取收藏状态 // 获取收藏状态
useEffect(() => { useEffect(() => {
@@ -198,7 +200,7 @@ export default function VideoCard({
router.push( router.push(
`/play?title=${encodeURIComponent(actualTitle.trim())}${ `/play?title=${encodeURIComponent(actualTitle.trim())}${
actualYear ? `&year=${actualYear}` : '' actualYear ? `&year=${actualYear}` : ''
}` }${actualSearchType ? `&stype=${actualSearchType}` : ''}`
); );
} else if (actualSource && actualId) { } else if (actualSource && actualId) {
router.push( router.push(