From 352edd86ed5e15d82c27890e2af6333216858340 Mon Sep 17 00:00:00 2001 From: ShukeBta Date: Thu, 28 May 2026 08:47:49 +0800 Subject: [PATCH] Fix series selection playback and query cleaning --- internal/service/scraper.go | 2 +- web/src/components/MediaCard.tsx | 27 ++++++++++++++--- web/src/pages/HomePage.tsx | 4 +-- web/src/pages/LibraryPage.tsx | 52 ++++++++++++++++++++++++-------- web/src/utils/groupSeries.ts | 17 ++++++----- 5 files changed, 74 insertions(+), 28 deletions(-) diff --git a/internal/service/scraper.go b/internal/service/scraper.go index 8ccf09f..14a9c2a 100644 --- a/internal/service/scraper.go +++ b/internal/service/scraper.go @@ -108,7 +108,7 @@ func CleanQuery(raw string) (title string, year int) { for _, t := range noiseTokens { lower = strings.ReplaceAll(lower, t, " ") } - for _, sep := range []string{".", "_", "-", "[", "]", "(", ")", "×", "x"} { + for _, sep := range []string{".", "_", "-", "[", "]", "(", ")", "×"} { lower = strings.ReplaceAll(lower, sep, " ") } // 拆分后丢掉过短(≤1)且全为 ASCII 数字 / 字母的"碎片",避免 diff --git a/web/src/components/MediaCard.tsx b/web/src/components/MediaCard.tsx index c0227f2..11587a5 100644 --- a/web/src/components/MediaCard.tsx +++ b/web/src/components/MediaCard.tsx @@ -6,15 +6,19 @@ import { imageURL } from '../api/client' import type { Media } from '../types' export const MediaCard = ({ - media, progress, count, rating, linkTo, + media, progress, count, rating, linkTo, onClick, }: { - media: Media; progress?: number; count?: number; rating?: number; linkTo?: string + media: Media + progress?: number + count?: number + rating?: number + linkTo?: string + onClick?: () => void }) => { const ref = useRef(null) const href = linkTo ?? `/media/${media.id}` - return ( - + const card = ( + ) + + if (onClick) { + return ( + + ) + } + + return ( + + {card} ) -} \ No newline at end of file +} diff --git a/web/src/pages/HomePage.tsx b/web/src/pages/HomePage.tsx index 78b4fec..ee2ebeb 100644 --- a/web/src/pages/HomePage.tsx +++ b/web/src/pages/HomePage.tsx @@ -228,7 +228,7 @@ export function HomePage() { key={s.rep.id} media={s.rep} count={s.count} - linkTo={s.count > 1 ? `/library/${row.library.id}` : undefined} + linkTo={s.count > 1 ? `/library/${row.library.id}?series=${encodeURIComponent(s.key)}` : undefined} /> ))} @@ -300,4 +300,4 @@ function ContinueCard({ media, progress }: { media: Media; progress: number }) { ) -} \ No newline at end of file +} diff --git a/web/src/pages/LibraryPage.tsx b/web/src/pages/LibraryPage.tsx index dd513c2..d73fef7 100644 --- a/web/src/pages/LibraryPage.tsx +++ b/web/src/pages/LibraryPage.tsx @@ -1,19 +1,19 @@ import { useEffect, useMemo, useState } from 'react' -import { Link, useParams, useNavigate } from 'react-router-dom' +import { Link, useParams, useSearchParams } from 'react-router-dom' import { motion, AnimatePresence } from 'framer-motion' import toast from 'react-hot-toast' -import { ArrowLeft, Play, Film, Layers } from 'lucide-react' +import { ArrowLeft, Play, Film } from 'lucide-react' import { libraryAPI } from '../api/library' import type { Library, Media } from '../types' import { MediaCard } from '../components/MediaCard' import { imageURL } from '../api/client' import { useAuthStore } from '../stores/auth' -import { groupSeries, type SeriesCard } from '../utils/groupSeries' +import { getSeriesKey, groupSeries, type SeriesCard } from '../utils/groupSeries' export function LibraryPage() { const { id = '' } = useParams() - const navigate = useNavigate() + const [searchParams, setSearchParams] = useSearchParams() const role = useAuthStore((s) => s.user?.role) const [library, setLibrary] = useState(null) @@ -37,10 +37,7 @@ export function LibraryPage() { // 选中的剧集:所有集按季分组 const selectedEpisodes = useMemo(() => { if (!selectedSeries || items.length === 0) return [] - const title = selectedSeries.rep.title.toLowerCase() - const eps = items.filter( - (m) => (m.title ?? '').toLowerCase() === title || m.tmdb_id === selectedSeries.rep.tmdb_id, - ) + const eps = items.filter((m) => getSeriesKey(m) === selectedSeries.key) // 按季分组,按集排序 const seasons = new Map() for (const ep of eps) { @@ -78,6 +75,22 @@ export function LibraryPage() { .finally(() => setLoading(false)) }, [id, library]) + useEffect(() => { + if (!isSeries) { + setSelectedSeries(null) + return + } + + const key = searchParams.get('series') + if (!key) { + setSelectedSeries(null) + return + } + + const next = seriesCards.find((card) => card.key === key) + if (next) setSelectedSeries(next) + }, [isSeries, searchParams, seriesCards]) + const handleScan = async () => { setScanning(true) try { @@ -100,9 +113,19 @@ export function LibraryPage() { const handleSeriesClick = (card: SeriesCard) => { setSelectedSeries(card) + const next = new URLSearchParams(searchParams) + next.set('series', card.key) + setSearchParams(next) window.scrollTo({ top: 0, behavior: 'smooth' }) } + const clearSelectedSeries = () => { + setSelectedSeries(null) + const next = new URLSearchParams(searchParams) + next.delete('series') + setSearchParams(next) + } + if (loading) { return (
@@ -153,9 +176,7 @@ export function LibraryPage() { {isSeries && seriesCards.length > 0 && !selectedSeries && (
{seriesCards.map((s) => ( - + handleSeriesClick(s)} /> ))}
)} @@ -172,7 +193,7 @@ export function LibraryPage() { {/* 返回按钮 + 标题 */}