'多语言'
This commit is contained in:
76
app/[locale]/course/VideoCard.tsx
Normal file
76
app/[locale]/course/VideoCard.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { generateVideoPoster } from "./videoPoster";
|
||||
|
||||
type Lesson = {
|
||||
id: string;
|
||||
title: string;
|
||||
duration: string;
|
||||
videoUrl?: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
lesson: Lesson;
|
||||
completed?: boolean;
|
||||
onComplete?: () => void;
|
||||
};
|
||||
|
||||
export function VideoCard({ lesson, completed = false, onComplete }: Props) {
|
||||
const [poster, setPoster] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setPoster(generateVideoPoster(lesson.title, lesson.id));
|
||||
}, [lesson.title, lesson.id]);
|
||||
|
||||
const handleEnded = useCallback(() => {
|
||||
onComplete?.();
|
||||
}, [onComplete]);
|
||||
|
||||
return (
|
||||
<article
|
||||
className={`group overflow-hidden rounded-2xl border shadow-sm transition-all duration-200 hover:shadow-md ${
|
||||
completed
|
||||
? "border-emerald-200 bg-emerald-50/50 hover:border-emerald-300"
|
||||
: "border-slate-100 bg-white hover:border-slate-200"
|
||||
}`}
|
||||
>
|
||||
{/* 三级标题:视频上方,突出显示 */}
|
||||
<div className="flex items-center gap-3 border-b border-slate-100 bg-white/80 px-4 py-3">
|
||||
<span
|
||||
className={`flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-xs font-bold ${
|
||||
completed ? "bg-emerald-100 text-emerald-600" : "bg-sky-50 text-sky-600"
|
||||
}`}
|
||||
>
|
||||
{lesson.id}
|
||||
</span>
|
||||
<h4 className="min-w-0 flex-1 text-base font-semibold leading-snug text-slate-800 line-clamp-2">
|
||||
{lesson.title}
|
||||
</h4>
|
||||
</div>
|
||||
<div className="relative aspect-video overflow-hidden bg-slate-900">
|
||||
<video
|
||||
src={lesson.videoUrl}
|
||||
poster={poster ?? undefined}
|
||||
controls
|
||||
playsInline
|
||||
onEnded={handleEnded}
|
||||
className="h-full w-full object-contain transition-transform duration-300 group-hover:scale-[1.01]"
|
||||
preload="metadata"
|
||||
>
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
<span className="absolute bottom-2 right-2 rounded bg-black/60 px-2 py-0.5 text-xs font-medium tabular-nums text-white/90 backdrop-blur-sm">
|
||||
{lesson.duration}
|
||||
</span>
|
||||
{completed && (
|
||||
<span className="absolute top-2 right-2 flex h-8 w-8 items-center justify-center rounded-full bg-emerald-500 text-white shadow-md">
|
||||
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user