"use client"; import { useState, useEffect } from "react"; import { useRouter, usePathname } from "next/navigation"; import { IconHeart } from "./Icons"; import { apiToggleLike } from "@/lib/api"; import { toast } from "@/lib/toast"; interface LikeButtonProps { postId: string; liked: boolean; likeCount: number; variant?: "default" | "compact" | "article"; } export default function LikeButton({ postId, liked: initialLiked, likeCount: initialCount, variant = "default", }: LikeButtonProps) { const router = useRouter(); const pathname = usePathname(); const [liked, setLiked] = useState(initialLiked); const [count, setCount] = useState(initialCount); const [loading, setLoading] = useState(false); // router.refresh()(登录/登出后)服务端会重新下发 liked 态,同步到本地, // 避免客户端状态停留在刷新前的用户视角 useEffect(() => { setLiked(initialLiked); setCount(initialCount); }, [initialLiked, initialCount]); const handleClick = async () => { if (loading) return; setLoading(true); // 乐观更新:先给反馈,失败再回滚 const wasLiked = liked; setLiked(!wasLiked); setCount((c) => c + (wasLiked ? -1 : 1)); try { const res = await apiToggleLike(postId); if (res.error === "未登录") { router.push(`/login?redirect=${encodeURIComponent(pathname)}`); return; } if (typeof res.liked === "boolean") { setLiked(res.liked); setCount(res.like_count ?? count); } else { throw new Error(res.error || "FAIL"); } } catch { setLiked(wasLiked); setCount((c) => c + (wasLiked ? 1 : -1)); toast("操作失败,请稍后重试"); } finally { setLoading(false); } }; const sizeCls = variant === "compact" ? "px-2.5 py-1.5 gap-1 text-[12.5px]" : variant === "article" ? "px-7 py-3 gap-2 text-[15px] min-w-[148px]" : "px-4 py-2 gap-1.5 text-sm"; const iconSize = variant === "compact" ? 13 : variant === "article" ? 18 : 15; return ( ); }