diff --git a/web/src/pages/AIAssistantPage.tsx b/web/src/pages/AIAssistantPage.tsx index 4395009..1ddfbf0 100644 --- a/web/src/pages/AIAssistantPage.tsx +++ b/web/src/pages/AIAssistantPage.tsx @@ -1,4 +1,4 @@ -import { FormEvent, useEffect, useState } from 'react' +import { FormEvent, useEffect, useMemo, useState } from 'react' import { Link } from 'react-router-dom' import { Loader2, Rss, Search, Sparkles, Wand2 } from 'lucide-react' import toast from 'react-hot-toast' @@ -8,6 +8,7 @@ import { imageURL } from '../api/client' import { subscriptionsAPI } from '../api/subscriptions' import { MediaCard } from '../components/MediaCard' import type { Media } from '../types' +import { groupSeries, seriesCardLink } from '../utils/groupSeries' // AIAssistantPage exposes the two AI helpers backed by the Go server: // - smart search: parses a natural-language query into a SearchIntent + @@ -30,6 +31,7 @@ export function AIAssistantPage() { const [items, setItems] = useState([]) const [externalItems, setExternalItems] = useState([]) const [subscribing, setSubscribing] = useState('') + const localCards = useMemo(() => groupSeries(items), [items]) const [recs, setRecs] = useState(null) const [recommending, setRecommending] = useState(false) @@ -186,11 +188,21 @@ export function AIAssistantPage() { )} - {items.length > 0 && ( -
- {items.map((m) => ( - - ))} + {localCards.length > 0 && ( +
+
+ 本地媒体库 · {localCards.length} 个合集 / {items.length} 个条目 +
+
+ {localCards.map((card) => ( + + ))} +
)} diff --git a/web/src/pages/LibrariesPage.tsx b/web/src/pages/LibrariesPage.tsx index 7202a52..58b5f94 100644 --- a/web/src/pages/LibrariesPage.tsx +++ b/web/src/pages/LibrariesPage.tsx @@ -7,7 +7,7 @@ import { imageURL } from '../api/client' import { libraryAPI } from '../api/library' import { MediaCard } from '../components/MediaCard' import type { Library, Media } from '../types' -import { artworkScore, groupSeries, type SeriesCard } from '../utils/groupSeries' +import { artworkScore, groupSeries, seriesCardLink, type SeriesCard } from '../utils/groupSeries' type LibraryPreview = { library: Library @@ -206,7 +206,7 @@ function LibraryShelf({ preview }: { preview: LibraryPreview }) {
))} @@ -226,13 +226,6 @@ function latestCards(items: Media[]): SeriesCard[] { .slice(0, 10) } -function mediaCardLink(card: SeriesCard): string { - if (card.count > 1) { - return `/library/${card.rep.library_id}?series=${encodeURIComponent(card.key)}` - } - return `/media/${card.rep.id}` -} - function mediaTime(media: Media): number { return Date.parse(media.updated_at || media.created_at || '') || 0 } diff --git a/web/src/pages/SearchPage.tsx b/web/src/pages/SearchPage.tsx index 802a593..05175d3 100644 --- a/web/src/pages/SearchPage.tsx +++ b/web/src/pages/SearchPage.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, FormEvent, useCallback, useEffect, useState } from 'react' +import { ChangeEvent, FormEvent, useCallback, useEffect, useMemo, useState } from 'react' import toast from 'react-hot-toast' import { Rss, Sparkles } from 'lucide-react' @@ -8,6 +8,7 @@ import { mediaAPI } from '../api/library' import { subscriptionsAPI } from '../api/subscriptions' import { MediaCard } from '../components/MediaCard' import type { Media } from '../types' +import { groupSeries, seriesCardLink } from '../utils/groupSeries' export function SearchPage() { const [q, setQ] = useState('') @@ -20,6 +21,7 @@ export function SearchPage() { const [hasSearched, setHasSearched] = useState(false) const [externalItems, setExternalItems] = useState([]) const [subscribing, setSubscribing] = useState('') + const localCards = useMemo(() => groupSeries(items), [items]) useEffect(() => { aiAPI @@ -84,7 +86,7 @@ export function SearchPage() { } } - const showEmpty = !loading && !error && hasSearched && items.length === 0 + const showEmpty = !loading && !error && hasSearched && localCards.length === 0 const showIdle = !loading && !error && !hasSearched return ( @@ -160,12 +162,19 @@ export function SearchPage() { )} - {items.length > 0 && ( + {localCards.length > 0 && ( <> -
本地媒体库
+
+ 本地媒体库 · {localCards.length} 个合集 / {items.length} 个条目 +
- {items.map((m) => ( - + {localCards.map((card) => ( + ))}
diff --git a/web/src/utils/groupSeries.ts b/web/src/utils/groupSeries.ts index 58e2afc..92cbad7 100644 --- a/web/src/utils/groupSeries.ts +++ b/web/src/utils/groupSeries.ts @@ -82,6 +82,13 @@ export function groupSeries(items: Media[]): SeriesCard[] { return Array.from(groups.values()) } +export function seriesCardLink(card: SeriesCard): string { + if (card.count > 1) { + return `/library/${card.rep.library_id}?series=${encodeURIComponent(card.key)}` + } + return `/media/${card.rep.id}` +} + export function artworkScore(media: Media): number { const poster = (media.poster_url ?? '').toLowerCase() const backdrop = (media.backdrop_url ?? '').toLowerCase()