"use client"; import { useState, useEffect, useCallback } from "react"; import { motion } from "motion/react"; import { FileText, AlertTriangle, CheckCircle, TrendingUp, Clock, ArrowRight, Loader2 } 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 TaskStats { monthly_tasks: number; pending_exceptions: number; completed_tasks: number; match_rate: number; current_period: string; } 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: "bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300" }, PROCESSING: { label: "处理中", color: "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300" }, MAPPING_COMPLETED: { label: "映射完成", color: "bg-amber-100 text-amber-700 dark:bg-amber-900/50 dark:text-amber-300" }, COMPLETED: { label: "已完成", color: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300" }, FAILED: { label: "失败", color: "bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-300" }, }; const container = { hidden: { opacity: 0 }, show: { opacity: 1, transition: { staggerChildren: 0.08, delayChildren: 0.1, }, }, }; const item = { hidden: { opacity: 0, y: 12 }, show: { opacity: 1, y: 0, transition: { duration: 0.4, ease: [0.16, 1, 0.3, 1] as const, }, }, }; export default function DashboardPage() { const router = useRouter(); const [stats, setStats] = useState(null); const [recentTasks, setRecentTasks] = useState([]); const [loading, setLoading] = useState(true); const loadDashboardData = useCallback(async () => { setLoading(true); try { // 并行获取统计数据和任务列表 const [statsRes, tasksRes] = await Promise.all([ api.get(ENDPOINTS.TASK.STATS), api.get(ENDPOINTS.TASK.LIST, { params: { limit: 5 } }), ]); setStats(statsRes.data); setRecentTasks(tasksRes.data); } catch (error) { console.error("加载数据失败:", error); } finally { setLoading(false); } }, []); useEffect(() => { loadDashboardData(); }, [loadDashboardData]); const formatPeriod = (period: string) => { const [year, month] = period.split("-"); return `${year}年${parseInt(month)}月`; }; return (
{/* Header */}

工作台

持续追踪您的对账任务

{loading ? (
) : ( <> {/* Stats Grid */}

本月任务

{stats?.monthly_tasks ?? 0}

{stats?.current_period ? formatPeriod(stats.current_period) : "-"}

待处理异常

{stats?.pending_exceptions ?? 0}

需要人工处理

已完成

{stats?.completed_tasks ?? 0}

本月累计

匹配率

{stats?.match_rate ?? 0}%

本月平均
{/* Recent Tasks */}

最近任务

{recentTasks.length === 0 ? (

暂无对账任务

创建您的第一个对账任务开始使用

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

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

{statusLabels[task.status]?.label || task.status}

{task.total_employees} 名员工 · {task.matched_count} 已匹配 · {task.exception_count} 异常

))}
)}
{/* Quick Actions */}

快捷操作

router.push("/tasks/new")} >

新建对账任务

上传工资表、社保表进行对账

router.push("/exceptions")} >

查看异常

处理待解决的异常记录

router.push("/settings/rules")} >

对账规则

配置对账规则和映射关系

)}
); }