From 480b38a5c5e48baecf09720de3f2aa7d638d89e1 Mon Sep 17 00:00:00 2001 From: shinya Date: Thu, 3 Jul 2025 18:56:37 +0800 Subject: [PATCH] feat: favorites in aggreagte page --- src/app/aggregate/page.tsx | 114 ++++++++++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 27 deletions(-) diff --git a/src/app/aggregate/page.tsx b/src/app/aggregate/page.tsx index f0fca45..c8072c1 100644 --- a/src/app/aggregate/page.tsx +++ b/src/app/aggregate/page.tsx @@ -2,11 +2,12 @@ 'use client'; -import { LinkIcon } from 'lucide-react'; +import { Heart, LinkIcon } from 'lucide-react'; import Image from 'next/image'; import { useRouter, useSearchParams } from 'next/navigation'; import { Suspense, useEffect, useState } from 'react'; +import { isFavorited, toggleFavorite } from '@/lib/db.client'; import { SearchResult } from '@/lib/types'; import PageLayout from '@/components/PageLayout'; @@ -142,6 +143,88 @@ function AggregatePageClient() { // 详情映射,便于快速获取每个源的集数 const sourceDetailMap = new Map(results.map((d) => [d.source, d])); + // 新增:播放源卡片组件,包含收藏逻辑 + const SourceCard = ({ src }: { src: SearchResult }) => { + const d = sourceDetailMap.get(src.source); + const epCount = d ? d.episodes.length : src.episodes.length; + + const [favorited, setFavorited] = useState(false); + + // 初次加载检查收藏状态 + useEffect(() => { + (async () => { + try { + const fav = await isFavorited(src.source, src.id); + setFavorited(fav); + } catch { + /* 忽略错误 */ + } + })(); + }, [src.source, src.id]); + + // 切换收藏状态 + const handleToggleFavorite = async ( + e: React.MouseEvent + ) => { + e.preventDefault(); + e.stopPropagation(); + + try { + const newState = await toggleFavorite(src.source, src.id, { + title: src.title, + source_name: src.source_name, + year: src.year, + cover: src.poster, + total_episodes: src.episodes.length, + save_time: Date.now(), + }); + setFavorited(newState); + } catch { + /* 忽略错误 */ + } + }; + + return ( + + {/* 收藏爱心 */} + + + + + {/* 名称 */} + + {src.source_name} + + {/* 集数徽标 */} + {epCount && epCount > 1 ? ( + + {epCount}集 + + ) : null} + + ); + }; + return (
@@ -247,32 +330,9 @@ function AggregatePageClient() {
- {uniqueSources.map((src) => { - const d = sourceDetailMap.get(src.source); - const epCount = d ? d.episodes.length : src.episodes.length; - return ( - - {/* 名称 */} - - {src.source_name} - - {/* 集数徽标 */} - {epCount && epCount > 1 ? ( - - {epCount}集 - - ) : null} - - ); - })} + {uniqueSources.map((src) => ( + + ))}
)}