import { useEffect, useState } from "react"; import { Package, ClipboardList, Bell, TrendingUp, AlertTriangle, RefreshCw, Loader2, AlertCircle, Plus, ArrowRight, } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { fetchDashboardStats, fetchRecentActivity, type DashboardStats, type RecentActivity, } from "../../services/dashboardApi"; // ─── 小卡片 ─────────────────────────────────────────────── function MiniStat({ value, label, color }: { value: number; label: string; color: string }) { return (
{value}

{label}

); } // ─── 进度条 ─────────────────────────────────────────────── function ProgressBar({ a, b, c, total, labels }: { a: number; b: number; c: number; total: number; labels: [string, string, string]; }) { if (total === 0) return
暂无数据
; const pct = (n: number) => Math.round((n / total) * 100); const segs = [ { n: a, color: "bg-amber-400", label: labels[0] }, { n: b, color: "bg-blue-500", label: labels[1] }, { n: c, color: "bg-emerald-500", label: labels[2] }, ].filter(s => s.n > 0); return (
{segs.map((s, i) => (
))}
{segs.map((s, i) => ( {s.label} {s.n}({pct(s.n)}%) ))}
); } // ─── 动态条目 ───────────────────────────────────────────── function ActivityItem({ a }: { a: RecentActivity }) { const iconMap: Record = { "创建任务": "📋", "确认接收": "✅", "完成任务": "🏁", "完工转交": "🔄", "品质驳回": "❌", "结束分支": "🛑", "撤回转交": "↩️", }; return (
{iconMap[a.action] || "📌"}
{a.action} {a.task_name}
{a.operator} · {a.product_sn.slice(0, 8)}… {a.time}
); } // ─── 主组件 ─────────────────────────────────────────────── export default function AdminDashboard() { const [stats, setStats] = useState(null); const [activity, setActivity] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const navigate = useNavigate(); useEffect(() => { Promise.all([ fetchDashboardStats(), fetchRecentActivity(8), ]) .then(([s, a]) => { setStats(s); setActivity(a); }) .catch(() => setError("加载统计数据失败,请确认后端已启动")) .finally(() => setLoading(false)); }, []); // ── 加载态 ── if (loading) { return (
); } // ── 错误态 ── if (error || !stats) { return (
{error || "数据为空"}
); } return (
{/* ═══ 页头 ═══ */}

📊 生产管理看板

产品 = 物理实体(身份证)| 任务 = 工序节点(流转步骤)

{/* ═══ 第1行:4 张概览卡片 ═══ */}
{/* 产品流转 */}

📦 产品流转

{stats.products_total} 个

已登记的物理产品数量

{/* 任务状态 */}

📋 任务状态

{stats.tasks_total} 个

产品下所有工序任务汇总

{/* 品质 & 通知 */}

⚠️ 品质 & 通知

{stats.tasks_rejected + stats.tasks_rework}

驳回/返工

{stats.unread_notifications}

未读通知

{/* 完成率 */}

✅ 流转完成率

{stats.tasks_total > 0 ? Math.round((stats.tasks_completed / stats.tasks_total) * 100) : 0}%

{stats.tasks_completed}/{stats.tasks_total} 已完成

{/* 简易环形图 */}
0 ? (stats.tasks_completed / stats.tasks_total) * 251 : 0} 251`} strokeLinecap="round" />
{/* ═══ 第2行:最近动态 + 快捷入口 ═══ */}
{/* 最近动态 */}

🕐 最近流转动态

最新 8 条
{activity.length === 0 ? (
暂无流转记录
) : (
{activity.map((a, i) => )}
)}
{/* 快捷入口 */}

⚡ 快捷入口

{/* 说明卡片 */}

💡 怎么理解?
一个产品从创建到入库,会经过多道 工序(装配→接线→质检…)。 每道工序就是一个任务,由不同工人完成。 所以任务数 ≥ 产品数是正常的。

); }