'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; import { useParams } from 'next/navigation'; import { Skeleton } from '@/components/ui/skeleton'; import { useT } from '@/i18n'; import { API_BASE } from '@/lib/config'; interface SkillTask { label: string; prompt: string } interface Skill { id: string; name: string; description: string; icon: string; category: string; difficulty: string; systemPrompt: string; starters: string[]; tasks: SkillTask[]; tags: string[]; prerequisites?: string[]; } interface AffiliateLink { id: number; title: string; description: string | null; url: string } export default function SkillDetailPage({ initialSkill }: { initialSkill?: Skill | null }) { const params = useParams(); const t = useT(); const [skill, setSkill] = useState(initialSkill ?? null); const [loading, setLoading] = useState(!initialSkill); const [links, setLinks] = useState([]); useEffect(() => { if (initialSkill) return; if (!params.id) return; fetch(`${API_BASE}/skills/${params.id}`) .then((r) => r.json()) .then((data) => { if (data.id) setSkill(data); }) .finally(() => setLoading(false)); }, [params.id, initialSkill]); useEffect(() => { if (!skill?.id) return; fetch(`${API_BASE}/affiliate/links?skillId=${skill.id}`) .then(r => r.json()) .then(data => setLinks(data.links || [])) .catch(() => {}); }, [skill?.id]); async function handlePromote(link: AffiliateLink) { try { const res = await fetch(`${API_BASE}/affiliate/click/${link.id}`, { method: 'POST' }); const data = await res.json(); if (data.redirectUrl) window.open(data.redirectUrl, '_blank', 'noopener,noreferrer'); } catch { window.open(link.url, '_blank', 'noopener,noreferrer'); } } if (loading) return (
); if (!skill) return (

技能不存在

返回技能库
); return (
← {t.skills.title}
{skill.icon}

{skill.name}

{skill.description}

{(t.skills as any)[skill.difficulty]} {(t.skills.categories as any)[skill.category] || skill.category}
{t.skills.apply}

{t.skills.starters}

{skill.starters.map((q, i) => (
{q}
))}

{t.skills.tasks}

{skill.tasks.map((task, i) => (
{task.label}
{task.prompt}
))}
{skill.prerequisites && skill.prerequisites.length > 0 && (

{t.skills.prerequisites}

{skill.prerequisites.map(pre => ( {pre} ))}
)} {links.length > 0 && (

{t.affiliate.recommendForSkill}

{links.map(link => (
{link.title}
{link.description && (
{link.description}
)}
))}
)}
); }