"use client"; import { useState, useEffect, useCallback } from "react"; import { motion } from "motion/react"; import { FileText, Filter, ArrowRight, Loader2, ChevronLeft, ChevronRight } from "lucide-react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { useRouter } from "next/navigation"; import { api } from "@/lib/api/client"; import ENDPOINTS from "@/lib/api/endpoints"; interface Task { id: number; period: string; status: string; total_employees: number; matched_count: number; exception_count: number; created_at: string; completed_at: string | null; } const statusLabels: Record = { PENDING: { label: "待处理", color: "text-gray-700 dark:text-gray-300", bgColor: "bg-gray-100 dark:bg-gray-800" }, PROCESSING: { label: "处理中", color: "text-blue-700 dark:text-blue-300", bgColor: "bg-blue-100 dark:bg-blue-900/50" }, MAPPING_COMPLETED: { label: "映射完成", color: "text-amber-700 dark:text-amber-300", bgColor: "bg-amber-100 dark:bg-amber-900/50" }, COMPLETED: { label: "已完成", color: "text-emerald-700 dark:text-emerald-300", bgColor: "bg-emerald-100 dark:bg-emerald-900/50" }, FAILED: { label: "失败", color: "text-red-700 dark:text-red-300", bgColor: "bg-red-100 dark:bg-red-900/50" }, }; // 生成可选月份列表(近12个月) const getAvailablePeriods = () => { const periods = []; const now = new Date(); for (let i = 0; i < 12; i++) { const date = new Date(now.getFullYear(), now.getMonth() - i, 1); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, "0"); periods.push(`${year}-${month}`); } return periods; }; const formatPeriod = (period: string) => { const [year, month] = period.split("-"); return `${year}年${parseInt(month)}月`; }; export default function TasksPage() { const router = useRouter(); const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(true); const [selectedPeriod, setSelectedPeriod] = useState(""); const [availablePeriods] = useState(getAvailablePeriods); const loadTasks = useCallback(async () => { try { setLoading(true); const params = selectedPeriod ? { period: selectedPeriod } : {}; const res = await api.get(ENDPOINTS.TASK.LIST, { params }); setTasks(res.data); } catch (error) { console.error("加载任务列表失败:", error); } finally { setLoading(false); } }, [selectedPeriod]); useEffect(() => { loadTasks(); }, [loadTasks]); const getMatchRate = (task: Task) => { if (task.total_employees === 0) return "0%"; const rate = Math.round((task.matched_count / task.total_employees) * 100); return `${rate}%`; }; return (
{/* Header */}

对账任务

管理所有对账任务,查看对账结果

{/* Filter Bar */}
筛选月份:
{availablePeriods.slice(0, 6).map((period) => ( ))}
{selectedPeriod && ( )}
{/* Tasks List */} {loading ? (
) : tasks.length === 0 ? (

暂无任务

{selectedPeriod ? `没有 ${formatPeriod(selectedPeriod)} 的对账任务` : "当前没有任何对账任务" }

) : (
{tasks.map((task, index) => ( router.push(`/tasks/${task.id}/result`)} >

{formatPeriod(task.period)} 对账任务

{statusLabels[task.status]?.label || task.status}
{task.total_employees} 名员工 {task.matched_count} 已匹配 0 ? "text-amber-600" : "text-muted-foreground"}`}> {task.exception_count} 异常 匹配率: {getMatchRate(task)}
{task.completed_at ? new Date(task.completed_at).toLocaleDateString("zh-CN") : new Date(task.created_at).toLocaleDateString("zh-CN") }
))}
)} {/* Pagination hint */} {tasks.length > 0 && (
显示最近 50 条记录
)}
); }