'use client'; import { useEffect, useState } from 'react'; import { Card } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { ExternalLink, Link as LinkIcon, DollarSign, ArrowUpRight, BarChart3 } from 'lucide-react'; import { API_BASE } from '@/lib/config'; import { useT } from '@/i18n'; interface AffiliateLink { id: number; title: string; description: string | null; url: string; thumbnail: string | null; isFeatured: boolean; tags: string | null; program?: { name: string; provider?: string | null }; } interface AffiliateStats { totalClicks: number; totalRevenue: number; topLinks: { id: number; title: string; clicks: number; estimatedRevenue: number }[]; } function SkeletonCard() { return (
); } export default function AffiliatePage() { const t = useT(); const [links, setLinks] = useState([]); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { Promise.all([ fetch(`${API_BASE}/affiliate/links`).then((r) => r.json()), fetch(`${API_BASE}/affiliate/stats`).then((r) => r.json()), ]) .then(([linksData, statsData]) => { setLinks(linksData.links || []); setStats(statsData); }) .catch(() => {}) .finally(() => setLoading(false)); }, []); 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'); } } return (

{t.affiliate.title}

{t.affiliate.desc}

{t.affiliate.totalClicks}

{(stats?.totalClicks ?? 0).toLocaleString()}

{t.affiliate.totalRevenue}

¥{(stats?.totalRevenue ?? 0).toLocaleString()}

{t.affiliate.partnerTools}

{links.length}

{t.affiliate.recommendTools}

{loading ? (
{[1, 2, 3, 4, 5, 6].map((i) => ( ))}
) : links.length === 0 ? ( {t.affiliate.noData} ) : (
{links.map((link) => (

{link.title}

{link.isFeatured && 推荐}
{link.program && (

{link.program.name}

)}

{link.description}

{link.tags && (
{link.tags .split(',') .slice(0, 3) .map((tag) => ( {tag} ))}
)}
))}
)}
{stats && stats.topLinks.length > 0 && (

{t.affiliate.ranking}

{stats.topLinks.map((item, index) => ( ))}
{t.affiliate.tool} {t.affiliate.clicks} {t.affiliate.revenue}
#{index + 1} {item.title} {item.clicks.toLocaleString()} ¥{item.estimatedRevenue.toFixed(2)}
)}

{t.affiliate.disclaimer}

); }