"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} router.push(recommendation.href)} > 执行 router.push("/dashboard/agents")} > 管理Agent router.push("/dashboard/lifecycle")} > 项目详情 {/* Agent Activity */} Agent活动 查看全部 {MOCK_AGENTS.map((agent) => ( ))} ); }
GEO和SEO是AI营销时代的共生体
{project.brand_name} — {project.name}
生命周期进度
推荐下一步
{recommendation.title}
{recommendation.description}
Agent活动