"use client"; import Link from "next/link"; import { CheckCircle2, ChevronUp, Loader2, X, XCircle } from "lucide-react"; import { useState } from "react"; import { createPortal } from "react-dom"; import { useJobs } from "@/components/layout/jobs-provider"; import { JobProgressPanel } from "@/components/job-progress-panel"; import { JOB_LABELS } from "@/lib/jobs/types"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; export function ActiveJobsPanel({ floating = false }: { floating?: boolean }) { const { jobs, activeJobs, cancelJob, cancellingId } = useJobs(); const [expanded, setExpanded] = useState(false); const progressType = (type: string) => type === "analyze-topic" ? "analyze-topic" : type === "style-8d" ? "style-8d" : type === "ai-task" ? "ai-task" : "scan"; const recentFinished = jobs .filter((job) => { if (job.status !== "completed" && job.status !== "failed") return false; const finishedAt = new Date(job.completedAt ?? job.createdAt).getTime(); const age = Date.now() - finishedAt; const window = job.type === "ai-task" ? 30 * 1000 : 3 * 60 * 1000; return age < window; }) .slice(0, 4); const visibleJobs = [...activeJobs, ...recentFinished.filter((job) => !activeJobs.some((active) => active.id === job.id))]; if (!floating && visibleJobs.length === 0) return null; if (floating) { const current = activeJobs[0] ?? recentFinished[0]; const running = activeJobs.length > 0; const panel = (
{running && ( {current.progress ?? current.label ?? JOB_LABELS[current.type as keyof typeof JOB_LABELS] ?? "任務進行中…"} )}
{expanded && (
任務中心

{visibleJobs.length === 0 ? "目前沒有任務" : "切換頁面不會中斷"}

{visibleJobs.length === 0 ? (

目前沒有進行中或最近完成的任務

) : ( visibleJobs.map((job) => (
{job.status === "running" || job.status === "pending" ? : job.status === "failed" ? : }

{job.label ?? JOB_LABELS[job.type as keyof typeof JOB_LABELS]}

{(job.status === "running" || job.status === "pending") && }
{job.error &&

錯誤:{job.error}

} {job.type === "style-8d" ? 查看帳號策略 : job.topicId && 查看任務}
)) )}
)}
); if (typeof document === "undefined") return panel; return createPortal(panel, document.body); } return ( 任務中心

可以自由切換頁面;分析與海巡會在背景繼續執行

{visibleJobs.map((job) => (
{job.status === "running" || job.status === "pending" ? : job.status === "failed" ? : }

{job.label ?? JOB_LABELS[job.type as keyof typeof JOB_LABELS]}

{(job.status === "running" || job.status === "pending") && }
{job.error &&

錯誤:{job.error}

}
{job.type === "style-8d" ? ( 查看帳號策略 ) : job.topicId && ( 查看主題 )}
))}
); }