"use client"; import { useState, useEffect } from "react"; import { useRouter, useParams } from "next/navigation"; import { useSession } from "next-auth/react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { FavoriteButton } from "@/components/common/FavoriteButton"; import { ReviewSection } from "@/components/common/ReviewSection"; interface ToolDetail { id: number; name: string; slug: string; description: string; logoUrl: string | null; websiteUrl: string; pricingModel: string; pricingDetail: string | null; features: unknown; tags: unknown; viewCount: number; favorited?: boolean; favoriteCount?: number; category: { id: number; name: string; slug: string } | null; createdAt: string; updatedAt: string; } const pricingLabel: Record = { free: "免费", freemium: "免费增值", paid: "付费", subscription: "订阅", }; const pricingColor: Record = { free: "bg-emerald-50 text-emerald-700 border border-emerald-200", freemium: "bg-blue-50 text-blue-700 border border-blue-200", paid: "bg-amber-50 text-amber-700 border border-amber-200", subscription: "bg-purple-50 text-purple-700 border border-purple-200", }; const pricingIcon: Record = { free: "M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z", freemium: "M13 10V3L4 14h7v7l9-11h-7z", paid: "M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z", subscription: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15", }; const tagColors = [ "border-blue-200 bg-blue-50 text-blue-700", "border-purple-200 bg-purple-50 text-purple-700", "border-emerald-200 bg-emerald-50 text-emerald-700", "border-amber-200 bg-amber-50 text-amber-700", "border-pink-200 bg-pink-50 text-pink-700", "border-cyan-200 bg-cyan-50 text-cyan-700", "border-indigo-200 bg-indigo-50 text-indigo-700", "border-rose-200 bg-rose-50 text-rose-700", ]; export default function ToolDetailPage() { const router = useRouter(); const params = useParams(); const slug = params.slug as string; const { status } = useSession(); const [tool, setTool] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); useEffect(() => { fetch(`/api/tools/${slug}`) .then((r) => { if (!r.ok) throw new Error("工具不存在"); return r.json(); }) .then((data) => { setTool(data); if (status === "authenticated" && data?.id) { fetch("/api/user/history", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ toolId: data.id }), }).catch(() => {}); } }) .catch((e) => setError(e.message)) .finally(() => setLoading(false)); }, [slug, status]); if (loading) { return (
); } if (error || !tool) { return (

{error || "工具不存在"}

); } const features = Array.isArray(tool.features) ? tool.features : []; const tags = Array.isArray(tool.tags) ? tool.tags : []; return (
{tool.logoUrl ? ( ) : (
{tool.name.charAt(0)}
)}

{tool.name}

{tool.category && ( )} {pricingLabel[tool.pricingModel] || tool.pricingModel} {tool.pricingDetail && ( {tool.pricingDetail} )} {tool.viewCount} 次浏览 {tool.favoriteCount !== undefined && ( {tool.favoriteCount} 人收藏 )}

简介

{tool.description || "暂无简介"}

{features.length > 0 && (

功能特性

    {features.map((f: string, i: number) => (
  • {f}
  • ))}
)} {tags.length > 0 && (

标签

{tags.map((t: string, i: number) => ( {t} ))}
)}
收录时间: {new Date(tool.createdAt).toLocaleDateString("zh-CN")} {tool.updatedAt !== tool.createdAt && ( 更新时间: {new Date(tool.updatedAt).toLocaleDateString("zh-CN")} )}
); }