import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '../../contexts/AuthContext'; import { supabase } from '../../supabase/client'; import { motion } from 'framer-motion'; import { FileText, Plus, Warehouse, Factory, ArrowLeft, Users, TrendingUp, Package, Clock, Building2, CheckCircle2, DollarSign, Droplets, LogOut, HelpCircle, X, BookOpen, MessageSquare, Info, Camera, ChevronRight, Home, MoreHorizontal, Calendar, Hash, Target, Activity, CreditCard } from 'lucide-react'; import { useResponsive } from '../../hooks/useResponsive'; import { OnboardingGuide, shouldShowOnboarding } from '../../components/OnboardingGuide'; import { NotificationCenter } from '../../components/NotificationCenter'; import { HelpCenter, HelpButton } from '../../components/HelpCenter'; import { VersionUpdate, useVersionCheck, AboutModal } from '../../components/VersionUpdate'; import { FeedbackModal } from '../../components/FeedbackModal'; import { UserManual } from '../../components/UserManual'; import type { ProductionPlan } from '../../types'; const statusMap: Record = { pending: { label: '待确定', color: 'text-amber-600', bgColor: 'bg-amber-50', borderColor: 'border-amber-200', icon: Clock }, producing: { label: '生产中', color: 'text-blue-600', bgColor: 'bg-blue-50', borderColor: 'border-blue-200', icon: TrendingUp }, completed: { label: '已完成', color: 'text-emerald-600', bgColor: 'bg-emerald-50', borderColor: 'border-emerald-200', icon: Package } }; const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.08 } } }; const itemVariants = { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] } } }; export function PurchaserDashboard() { const navigate = useNavigate(); const { auth, logout } = useAuth(); const { isMobile } = useResponsive(); const [plans, setPlans] = useState([]); const [loading, setLoading] = useState(true); const [dataLoaded, setDataLoaded] = useState(false); // 帮助中心状态 const [showHelp, setShowHelp] = useState(false); const [showOnboarding, setShowOnboarding] = useState(false); const [showUserManual, setShowUserManual] = useState(false); const [showFeedback, setShowFeedback] = useState(false); const [showAbout, setShowAbout] = useState(false); // 账户卡片弹窗状态 const [showAccountCard, setShowAccountCard] = useState(false); // 版本更新检查 const { showUpdate, setShowUpdate } = useVersionCheck(); // 检查是否显示新手引导 useEffect(() => { if (shouldShowOnboarding('purchaser')) { setShowOnboarding(true); } }, []); useEffect(() => { if (!auth.company) return; // 如果数据已加载,不再重新加载 if (dataLoaded && plans.length > 0) { setLoading(false); return; } fetchPlans(); }, [auth.company, dataLoaded, plans.length]); const fetchPlans = async () => { const { data: planData } = await supabase .from('production_plans') .select('*') .eq('purchaser_id', auth.company!.id) .order('created_at', { ascending: false }); // 获取流程步骤,检测 rejected 状态 const planIds = (planData || []).map(p => p.id); const { data: stepsData } = await supabase .from('plan_process_steps') .select('plan_id, status') .in('plan_id', planIds); // 过滤掉有 rejected 步骤的计划 const rejectedPlanIds = new Set(); (stepsData || []).forEach(step => { if (step.status === 'rejected') { rejectedPlanIds.add(step.plan_id); } }); const filteredPlans = (planData || []).filter(p => !rejectedPlanIds.has(p.id)); setPlans(filteredPlans); setLoading(false); setDataLoaded(true); }; // 监听页面可见性变化,返回页面时刷新数据 useEffect(() => { const handleVisibilityChange = () => { if (document.visibilityState === 'visible' && auth.company) { // 页面重新可见时刷新数据 fetchPlans(); } }; document.addEventListener('visibilitychange', handleVisibilityChange); return () => document.removeEventListener('visibilitychange', handleVisibilityChange); }, [auth.company]); const stats = { all: plans.length, producing: plans.filter(p => p.status === 'producing').length, completed: plans.filter(p => p.status === 'completed').length, pending: plans.filter(p => p.status === 'pending').length }; // 获取最近计划(桌面端显示更多) const recentPlans = plans.slice(0, isMobile ? 5 : 10); const producingPlans = plans.filter(p => p.status === 'producing').slice(0, isMobile ? 5 : 6); // 桌面端统计卡片数据 const statCards = [ { id: 'all', label: '所有计划', value: stats.all, sublabel: '累计创建', icon: FileText, color: 'from-blue-500 to-indigo-600', bgColor: 'bg-blue-50', textColor: 'text-blue-600', path: '/purchaser/plans' }, { id: 'producing', label: '进行中', value: stats.producing, sublabel: '正在生产', icon: TrendingUp, color: 'from-emerald-500 to-teal-600', bgColor: 'bg-emerald-50', textColor: 'text-emerald-600', path: '/purchaser/plans?filter=producing' }, { id: 'completed', label: '已完成', value: stats.completed, sublabel: '已入库', icon: Package, color: 'from-amber-500 to-orange-600', bgColor: 'bg-amber-50', textColor: 'text-amber-600', path: '/purchaser/plans?filter=completed' }, { id: 'pending', label: '待确定', value: stats.pending, sublabel: '等待确认', icon: Clock, color: 'from-purple-500 to-violet-600', bgColor: 'bg-purple-50', textColor: 'text-purple-600', path: '/purchaser/plans?filter=pending' } ]; // 快捷操作数据 const quickActions = [ { id: 'new', icon: Plus, label: '新建纺织计划', path: '/purchaser/plans/new', gradient: 'from-amber-400 to-orange-500', description: '创建新纺织计划' }, { id: 'washing', icon: Droplets, label: '新建水洗计划', path: '/purchaser/washing-plans/new', gradient: 'from-cyan-400 to-blue-500', description: '创建水洗计划' }, { id: 'warehouse', icon: Warehouse, label: '产品信息', path: '/purchaser/warehouse', gradient: 'from-emerald-400 to-teal-500', description: '管理产品库存' }, { id: 'washing-warehouse', icon: Droplets, label: '水洗仓库', path: '/purchaser/finished-warehouse', gradient: 'from-blue-400 to-indigo-500', description: '管理水洗库存' }, { id: 'factories', icon: Factory, label: '工厂管理', path: '/purchaser/factories', gradient: 'from-rose-400 to-pink-500', description: '管理合作工厂' }, { id: 'payables', icon: CreditCard, label: '应付账款', path: '/purchaser/accounts-payable', gradient: 'from-violet-400 to-purple-500', description: '查看应付账款' } ]; // 移动端当前计划索引(用于滑动) const [currentPlanIndex, setCurrentPlanIndex] = useState(0); return (
{/* 主内容区 - 由 PurchaserLayout 提供侧边栏(仅桌面端) */}
{/* Header - 与纺织厂保持一致 */}

{(auth.user as any)?.display_name || auth.user?.username || '用户'} {auth.company?.name || '采购商'}工作台 限时免费

{(auth.user as any)?.display_name || auth.user?.username || '用户'},欢迎回来

setShowHelp(true)} />
{/* 页面内容 */}
{loading ? (
) : (
{/* 统计卡片 - 移动端3列紧凑布局,桌面端4列 */}
{/* 移动端只显示3个统计卡片 */} {statCards.slice(0, isMobile ? 3 : 4).map((stat) => (
navigate(stat.path)} className="bg-white rounded-xl sm:rounded-2xl p-3 sm:p-5 shadow-sm border border-slate-200 cursor-pointer hover:border-amber-300 hover:shadow-md transition-all" >

{stat.label}

{stat.value}

{stat.sublabel}

))}
{/* 最近计划 - 移动端左右滑动,桌面端列表 */}

最近计划

{recentPlans.length === 0 ? (

暂无计划

点击快捷操作创建计划

) : (
{/* 滑动容器 - 移动端 */} {isMobile ? ( <>
{recentPlans.map((plan) => { const progress = plan.target_quantity > 0 ? Math.round((plan.completed_quantity / plan.target_quantity) * 100) : 0; const status = statusMap[plan.status] || statusMap.pending; const StatusIcon = status.icon; return (
navigate(`/purchaser/plans?id=${plan.id}`)} >
{/* 计划标题行 */}

{plan.product_name}

{status.label}

{plan.fabric_code}

{/* 进度信息 */}
进度 {progress}% {plan.completed_quantity}/{plan.target_quantity}米
); })}
{/* 左右滑动按钮 */} {recentPlans.length > 1 && ( <> )} {/* 指示器 */} {recentPlans.length > 1 && (
{recentPlans.map((_, i) => (
)} ) : ( /* 桌面端列表布局 */
{recentPlans.map((plan) => { const progress = plan.target_quantity > 0 ? Math.round((plan.completed_quantity / plan.target_quantity) * 100) : 0; const status = statusMap[plan.status] || statusMap.pending; const StatusIcon = status.icon; return ( navigate(`/purchaser/plans?id=${plan.id}`)} className="group p-4 rounded-xl border border-slate-200 hover:border-amber-300 hover:shadow-md cursor-pointer transition-all bg-slate-50/50 hover:bg-white" >

{plan.product_name}

{status.label}
{plan.fabric_code} {plan.target_quantity}米 进度 {progress}%
{/* 进度条 */}
= 100 ? 'bg-gradient-to-r from-emerald-500 to-teal-500' : progress >= 50 ? 'bg-gradient-to-r from-amber-500 to-orange-500' : 'bg-gradient-to-r from-blue-500 to-indigo-500' }`} />
); })}
)}
)}
{/* 快捷操作 - 移动端显示 */} {isMobile && (

快捷操作

{quickActions.map((action) => ( ))}
)}
)}
{/* 帮助中心弹窗 */} setShowHelp(false)} /> {/* 新手引导 */} setShowOnboarding(false)} /> {/* 用户手册 */} setShowUserManual(false)} /> {/* 反馈弹窗 */} setShowFeedback(false)} /> {/* 关于窗口 */} setShowAbout(false)} /> {/* 版本更新弹窗 */} setShowUpdate(false)} /> {/* 账户卡片弹窗 */} {showAccountCard && (
setShowAccountCard(false)}> e.stopPropagation()} > {/* 头部 */}

账户信息

{/* 账户详情 */}
{/* 用户信息 */}

{(auth.user as any)?.display_name || auth.user?.username || '用户'}

{auth.company?.name || '采购商'}

{auth.user?.is_master ? '主账号' : '子账号'}
{/* 功能菜单 */}
{/* 退出登录 */}
)}
); }