refactor(components): 优化卡片组件样式和交互逻辑

统一调整集数展示框的样式和交互效果
简化搜索页状态初始化逻辑
移除收藏功能的即时UI更新
This commit is contained in:
SongPro
2025-07-03 17:15:50 +08:00
parent c678534722
commit 020cb6b6b9
4 changed files with 34 additions and 47 deletions

View File

@@ -52,7 +52,7 @@ function PlayCircleSolid({
}
/**
* 与 `VideoCard` 基本一致,删除了集数徽标、来源标签、收藏等功能
* 与 `VideoCard` 基本一致,删除了来源标签、收藏等功能
* 点击播放按钮 -> 跳到第一个源播放
* 点击卡片其他区域 -> 跳到聚合详情页 (/aggregate)
*/
@@ -161,9 +161,9 @@ const AggregateCard: React.FC<AggregateCardProps> = ({
</div>
</div>
{/* 集数矩形展示框 - 不透明无hover效果 */}
{/* 集数矩形展示框 */}
{mostFrequentEpisodes && mostFrequentEpisodes > 1 && (
<div className='absolute top-2 right-2 min-w-[1.875rem] h-5 sm:h-7 sm:min-w-[2.5rem] bg-green-500 dark:bg-green-600 rounded-md flex items-center justify-center px-2 shadow-md text-[0.55rem] sm:text-xs'>
<div className='absolute top-2 right-2 w-7 h-7 sm:w-7 sm:h-7 rounded-full bg-green-500/90 dark:bg-green-600/90 flex items-center justify-center shadow-md text-[0.55rem] sm:text-xs'>
<span className='text-white font-bold leading-none'>
{mostFrequentEpisodes}
</span>

View File

@@ -1,7 +1,7 @@
import { Link as LinkIcon, Search } from 'lucide-react';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
import React from 'react';
import React, { useState } from 'react';
interface DemoCardProps {
id: string;
@@ -45,6 +45,7 @@ function SearchCircle({
}
const DemoCard = ({ id, title, poster, rate, type }: DemoCardProps) => {
const [hover, setHover] = useState(false);
const router = useRouter();
const handleClick = () => {
@@ -57,7 +58,7 @@ const DemoCard = ({ id, title, poster, rate, type }: DemoCardProps) => {
onClick={handleClick}
>
{/* 海报图片区域 */}
<div className='relative aspect-[2/3] w-full overflow-hidden rounded-md transition-all duration-400 cubic-bezier(0.4, 0, 0.2, 1)'>
<div className='relative aspect-[2/3] w-full overflow-hidden rounded-md group-hover:scale-[1.02] transition-all duration-400 cubic-bezier(0.4, 0, 0.2, 1) safari-fix'>
<Image
src={poster}
alt={title}
@@ -77,12 +78,15 @@ const DemoCard = ({ id, title, poster, rate, type }: DemoCardProps) => {
)}
{/* 悬浮层 - 搜索按钮 */}
<div
style={{ willChange: 'opacity' }}
className='absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300 cubic-bezier(0.4, 0, 0.2, 1) flex items-center justify-center'
>
<div className='transition-all duration-300 cubic-bezier(0.4, 0, 0.2, 1) scale-90 group-hover:scale-110 group-hover:rotate-12'>
<SearchCircle className='group-hover:fill-green-500' />
<div className='absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300 cubic-bezier(0.4, 0, 0.2, 1) flex items-center justify-center'>
<div
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
className={`transition-all duration-300 cubic-bezier(0.4, 0, 0.2, 1) ${
hover ? 'scale-110 rotate-12' : 'scale-90'
}`}
>
<SearchCircle fillColor={hover ? '#22c55e' : 'none'} />
</div>
</div>

View File

@@ -111,12 +111,6 @@ export default function VideoCard({
e.preventDefault();
e.stopPropagation();
// 如果是从收藏夹移除立即更新UI
if (favorited && from === 'favorites') {
setIsDeleting(true);
onDelete?.();
}
try {
const newState = await toggleFavorite(source, id, {
title,
@@ -237,23 +231,23 @@ export default function VideoCard({
</div>
</div>
{/* 集数矩形展示框 - 增加条件判断:仅当有多个集数且已播放时显示 */}
{/* 继续观看 - 集数矩形展示框 */}
{episodes && episodes > 1 && currentEpisode && (
<div className='absolute top-2 right-2 min-w-[1.875rem] h-5 sm:h-7 sm:min-w-[2.5rem] bg-green-500/90 dark:bg-green-600/90 rounded-md flex items-center justify-center px-2 shadow-md text-[0.55rem] sm:text-xs'>
<span className='text-white font-bold leading-none'>
{currentEpisode}
<span className='mx-1 text-white/80'>/</span>
</span>
<span className='mx-1 text-white/80'>/</span>
<span className='text-white font-bold leading-none'>
{episodes}
</span>
</div>
)}
{/* 集数圆形展示框 - 无当前集数且总集数大于 1 时展示 */}
{episodes && episodes > 1 && !currentEpisode && (
<div className='absolute top-2 right-2 w-4 h-4 sm:w-7 sm:h-7 bg-green-500 rounded-full flex items-center justify-center'>
<span className='text-white text-[0.5rem] sm:text-xs font-bold'>
{/* 搜索非聚合 - 集数圆形展示 */}
{from === 'search' && (
<div className='absolute top-2 right-2 w-4 h-4 sm:w-7 sm:h-7 rounded-full bg-green-500/90 dark:bg-green-600/90 flex items-center justify-center shadow-md text-[0.55rem] sm:text-xs'>
<span className='text-white font-bold leading-none'>
{episodes}
</span>
</div>