import { Metadata } from 'next'; import { notFound } from 'next/navigation'; import Link from 'next/link'; import { SITE_URL } from '@/lib/config'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { Wrench, ExternalLink, Star, ArrowLeft } from 'lucide-react'; interface ToolDetail { id: number; slug: string; name: string; metaTitle: string | null; metaDesc: string | null; description: string | null; content: string | null; url: string; icon: string | null; affiliateLink: string | null; tags: string | null; isFeatured: boolean; viewCount: number; category: { id: number; name: string } | null; } async function getTool(slug: string): Promise { try { const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000/api/v1'}/tools/${slug}`, { next: { revalidate: 3600 }, }); if (!res.ok) return null; return res.json(); } catch { return null; } } export async function generateMetadata({ params }: { params: { slug: string } }): Promise { const tool = await getTool(params.slug); if (!tool) return { title: '工具未找到' }; return { title: tool.metaTitle || `${tool.name} - 功能介绍、使用教程、评测 | 宇之然 AI 工具指南`, description: tool.metaDesc || tool.description || `${tool.name} AI工具详细介绍、使用教程和评测`, openGraph: { title: tool.metaTitle || `${tool.name} - AI工具评测`, description: tool.metaDesc || tool.description || '', type: 'article', }, }; } export async function generateStaticParams() { let apiBase = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000/api/v1'; // Build-time fetch requires absolute URL; if relative, prefix localhost:4000 if (!apiBase.startsWith('http')) { apiBase = `http://localhost:4000${apiBase.startsWith('/') ? '' : '/'}${apiBase}`; } try { const res = await fetch(`${apiBase}/tools?pageSize=100`); const data = await res.json(); return (data.items || []).map((tool: any) => ({ slug: tool.slug })); } catch { return []; } } export default async function ToolDetailPage({ params }: { params: { slug: string } }) { const tool = await getTool(params.slug); if (!tool) notFound(); const jsonLd = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: tool.name, description: tool.description || '', url: tool.url, applicationCategory: 'UtilitiesApplication', operatingSystem: 'Web', offers: { '@type': 'Offer', price: '0', priceCurrency: 'CNY' }, publisher: { '@type': 'Organization', name: '宇之然 AI', url: SITE_URL, logo: { '@type': 'ImageObject', url: `${SITE_URL}/favicon.png` }, }, }; // 解析描述中的结构化字段 function parseSection(desc: string | null, key: string): string | null { if (!desc) return null; const match = desc.match(new RegExp(`【${key}】\\s*(.+?)(?:\\n\\n|$)`, 's')); return match ? match[1].trim() : null; } function parseBaseDesc(desc: string | null): string { if (!desc) return ''; return desc.split('\n\n')[0] || ''; } const reason = parseSection(tool.description, '推荐理由'); const audience = parseSection(tool.description, '适合人群'); const baseDesc = parseBaseDesc(tool.description); // 收益标签映射 const roiTags: Record = { '编程': '日省2-4小时编码时间', '图像': '替代部分设计师,省¥1000-5000/月', '视频': '短视频效率提升5-10倍', '对话': '替代部分人工客服,省¥3000-8000/月', '办公': '文档效率提升3-5倍', '搜索': '调研效率提升5-10倍', '语音': '语音处理效率提升10倍', }; const category = tool.tags ? tool.tags.split(',')[0] : ''; const roiTag = roiTags[category] || '提升工作效率'; return ( <>