"use client"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { MetricCard, StageProgress, AgentStatusCard, } from "@/components/business"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Sparkles, Search, FileText, Send, BarChart3, Target, Plus, ArrowRight, Zap, } from "lucide-react"; import { type GeoProject, type LifecycleStats } from "@/lib/api"; import { useApi } from "@/lib/hooks/use-api"; import { LoadingState, ErrorState, EmptyState } from "@/components/ui/api-states"; /* ─── Helpers ─────────────────────────────────────────────────────────────────*/ const STAGE_CONFIG = [ { id: "diagnosis", label: "诊断分析" }, { id: "strategy", label: "策略制定" }, { id: "content", label: "内容生产" }, { id: "publishing", label: "分发执行" }, { id: "monitoring", label: "监测优化" }, ]; const MOCK_AGENTS = [ { name: "内容生成Agent", description: "自动化内容生产", status: "busy" as const, lastActiveAt: "2分钟前", completedCount: 156, }, { name: "引用监测Agent", description: "AI平台引用追踪", status: "online" as const, lastActiveAt: "刚刚", completedCount: 3420, }, { name: "SEO诊断Agent", description: "搜索引擎优化分析", status: "offline" as const, lastActiveAt: "3小时前", completedCount: 89, }, ]; function buildStages(currentStage: GeoProject["current_stage"]) { const currentIndex = STAGE_CONFIG.findIndex((s) => s.id === currentStage); return STAGE_CONFIG.map((stage, idx) => { let status: "completed" | "active" | "pending" | "error" = "pending"; if (idx < currentIndex) status = "completed"; else if (idx === currentIndex) status = "active"; return { id: stage.id, label: stage.label, status }; }); } function getRecommendation(stage: GeoProject["current_stage"]) { const map: Record< GeoProject["current_stage"], { title: string; description: string; icon: React.ReactNode; href: string } > = { diagnosis: { title: "开始诊断分析", description: "诊断您品牌在AI搜索中的可见性现状", icon: , href: "/dashboard/diagnosis", }, strategy: { title: "生成优化策略", description: "基于诊断结果制定GEO+SEO优化方案", icon: , href: "/dashboard/strategy", }, content: { title: "创建新内容", description: "使用AI Agent批量生成优化内容", icon: , href: "/dashboard/content", }, publishing: { title: "配置分发渠道", description: "将内容分发到各大AI平台和搜索引擎", icon: , href: "/dashboard/publishing", }, monitoring: { title: "查看监测报告", description: "分析内容分发后的引用和排名数据", icon: , href: "/dashboard/monitoring", }, }; return map[stage]; } /* ─── Component ───────────────────────────────────────────────────────────────*/ export default function DashboardPage() { const router = useRouter(); const { data: projects, isLoading: projectsLoading, error: projectsError, refresh: refreshProjects, } = useApi("/api/v1/lifecycle/projects/"); const { data: stats, isLoading: statsLoading, error: statsError, refresh: refreshStats, } = useApi("/api/v1/lifecycle/projects/stats"); const loading = projectsLoading || statsLoading; // "用户未关联组织" 类错误视为空状态 const isOrgError = (err: Error | undefined) => err?.message.includes("未关联组织") || err?.message.includes("No organization"); const hasOrgError = isOrgError(projectsError) || isOrgError(statsError); const error = !hasOrgError && (projectsError || statsError) ? projectsError || statsError : undefined; const safeProjects: GeoProject[] = hasOrgError ? [] : (projects ?? []); const safeStats: LifecycleStats | null = hasOrgError ? null : (stats ?? null); const handleRetry = () => { refreshProjects(); refreshStats(); }; /* ─── Loading State ────────────────────────────────────────────────────────*/ if (loading) { return (
); } /* ─── Error State ──────────────────────────────────────────────────────────*/ if (error) { return (

Overview

); } /* ─── Empty State ──────────────────────────────────────────────────────────*/ if (safeProjects.length === 0) { return (

Overview

GEO和SEO是AI营销时代的共生体

} message="开始优化您的AI可见性" description="创建第一个项目,系统将自动引导您完成从诊断分析到监测优化的全生命周期管理。" action={ } />
); } /* ─── Active Dashboard ─────────────────────────────────────────────────────*/ const project = safeProjects[0]; const stages = buildStages(project.current_stage); const recommendation = getRecommendation(project.current_stage); const citationRate = safeStats?.avg_ai_citation_rate != null ? `${(safeStats.avg_ai_citation_rate * 100).toFixed(1)}%` : "—"; return (
{/* 1. Page Title */}

Overview

{project.brand_name} — {project.name}

{/* 2. KPI Cards */}
{/* 3. Stage Progress */}

生命周期进度

当前阶段: {STAGE_CONFIG.find((s) => s.id === project.current_stage)?.label}
{ router.push(`/dashboard/${stage.id}`); }} />
{/* 4. Two-column: Recommendation + Agent Activity */}
{/* Recommendation */}

推荐下一步

{recommendation.icon}

{recommendation.title}

{recommendation.description}

{/* Agent Activity */}

Agent活动

查看全部
{MOCK_AGENTS.map((agent) => ( ))}
); }