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 (
);
}
// ─── 进度条 ───────────────────────────────────────────────
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 (
);
}
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} 已完成
{/* 简易环形图 */}
{/* ═══ 第2行:最近动态 + 快捷入口 ═══ */}
{/* 最近动态 */}
🕐 最近流转动态
最新 8 条
{activity.length === 0 ? (
暂无流转记录
) : (
{activity.map((a, i) =>
)}
)}
{/* 快捷入口 */}
⚡ 快捷入口
{/* 说明卡片 */}
💡 怎么理解?
一个产品从创建到入库,会经过多道
工序(装配→接线→质检…)。
每道工序就是一个任务,由不同工人完成。
所以任务数 ≥ 产品数是正常的。
);
}