【码源】智能无人仓库管理系统(详细码源下~基于React+TypeScript+Vite):

【码源】智能无人仓库管理系统(详细码源下~基于React+TypeScript+Vite):

详细码源下:

InventoryManagement.tsx #库存管理:
bash 复制代码
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { 
  Database, Search, Plus, Edit, Eye, Filter, X, 
  AlertCircle, ChevronDown, RefreshCw, BarChart2,
  PackageCheck, PackageOpen, MoveHorizontal, Calendar,
  CheckCircle, TrendingUp, TrendingDown, ArrowUp, ArrowDown
} from 'lucide-react';
import { 
  BarChart, Bar, LineChart, Line, PieChart, Pie,
  XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer,
  Cell
} from 'recharts';
import { useTheme } from '@/hooks/useTheme';
import { toast } from 'sonner';

// 库存警报类型定义
interface InventoryAlert {
  id: string;
  goodsId: string;
  goodsName: string;
  category: string;
  currentStock: number;
  threshold: number;
  location: string;
  alertType: 'low-stock' | 'expiring-soon' | 'excess-stock';
  alertTime: string;
  status: 'pending' | 'processed';
}

// 库存移动记录类型定义
interface InventoryMovement {
  id: string;
  goodsId: string;
  goodsName: string;
  movementType: 'in' | 'out' | 'transfer';
  quantity: number;
  fromLocation: string;
  toLocation: string;
  operator: string;
  movementTime: string;
  reason: string;
}

// 库存盘点类型定义
interface InventoryCheck {
  id: string;
  name: string;
  status: 'pending' | 'in-progress' | 'completed' | 'cancelled';
  startTime: string;
  endTime: string | null;
  checkedBy: string;
  discrepancyCount: number;
  totalItems: number;
}

// 库存分类统计类型定义
interface CategoryStat {
  name: string;
  value: number;
  inStock: number;
  lowStock: number;
  outOfStock: number;
}

// 模拟库存警报数据
const generateMockAlerts = (): InventoryAlert[] => {
  const categories = ['电子产品', '服装鞋帽', '食品饮料', '家居用品', '其他'];
  const alertTypes: Array<'low-stock' | 'expiring-soon' | 'excess-stock'> = ['low-stock', 'expiring-soon', 'excess-stock'];
  const locations = ['A区-01-01', 'A区-01-02', 'A区-02-01', 'B区-01-01', 'B区-02-01', 'C区-01-01'];
  
  return Array.from({ length: 15 }, (_, index) => {
    const alertType = alertTypes[Math.floor(Math.random() * alertTypes.length)];
    const threshold = Math.floor(Math.random() * 50) + 10;
    const currentStock = alertType === 'low-stock' 
      ? Math.floor(Math.random() * threshold)
      : alertType === 'excess-stock'
        ? threshold * (Math.floor(Math.random() * 5) + 3)
        : Math.floor(Math.random() * 200) + 50;
    
    return {
      id: `ALERT-${String(index + 1).padStart(4, '0')}`,
      goodsId: `GOODS-${String(Math.floor(Math.random() * 100)).padStart(4, '0')}`,
      goodsName: `货物名称 ${Math.floor(Math.random() * 100) + 1}`,
      category: categories[Math.floor(Math.random() * categories.length)],
      currentStock,
      threshold,
      location: locations[Math.floor(Math.random() * locations.length)],
      alertType,
      alertTime: new Date(Date.now() - Math.floor(Math.random() * 7) * 24 * 60 * 60 * 1000).toLocaleString('zh-CN'),
      status: Math.random() > 0.5 ? 'pending' : 'processed'
    };
  });
};

// 模拟库存移动记录数据
const generateMockMovements = (): InventoryMovement[] => {
  const movementTypes: Array<'in' | 'out' | 'transfer'> = ['in', 'out', 'transfer'];
  const locations = ['A区-01-01', 'A区-01-02', 'A区-02-01', 'B区-01-01', 'B区-02-01', 'C区-01-01'];
  const reasons = ['采购入库', '销售出库', '内部移库', '盘点调整', '质量问题退货', '客户订单发货'];
  const operators = ['系统自动', '管理员', '操作员A', '操作员B', '操作员C'];
  
  return Array.from({ length: 50 }, (_, index) => {
    const movementType = movementTypes[Math.floor(Math.random() * movementTypes.length)];
    
    return {
      id: `MOVE-${String(index + 1).padStart(4, '0')}`,
      goodsId: `GOODS-${String(Math.floor(Math.random() * 100)).padStart(4, '0')}`,
      goodsName: `货物名称 ${Math.floor(Math.random() * 100) + 1}`,
      movementType,
      quantity: Math.floor(Math.random() * 200) + 10,
      fromLocation: movementType === 'in' ? '外部' : locations[Math.floor(Math.random() * locations.length)],
      toLocation: movementType === 'out' ? '外部' : locations[Math.floor(Math.random() * locations.length)],
      operator: operators[Math.floor(Math.random() * operators.length)],
      movementTime: new Date(Date.now() - Math.floor(Math.random() * 30) * 24 * 60 * 60 * 1000).toLocaleString('zh-CN'),
      reason: reasons[Math.floor(Math.random() * reasons.length)]
    };
  });
};

// 模拟库存盘点数据
const generateMockChecks = (): InventoryCheck[] => {
  const statuses: Array<'pending' | 'in-progress' | 'completed' | 'cancelled'> = ['pending', 'in-progress', 'completed', 'cancelled'];
  const checkers = ['管理员', '操作员A', '操作员B', '系统自动'];
  
  return Array.from({ length: 10 }, (_, index) => {
    const status = statuses[Math.floor(Math.random() * statuses.length)];
    const startDate = new Date(Date.now() - Math.floor(Math.random() * 90) * 24 * 60 * 60 * 1000);
    const endDate = status === 'completed' 
      ? new Date(startDate.getTime() + Math.floor(Math.random() * 3) * 24 * 60 * 60 * 1000) 
      : null;
    const totalItems = Math.floor(Math.random() * 300) + 50;
    
    return {
      id: `CHECK-${String(index + 1).padStart(4, '0')}`,
      name: `${index % 3 === 0 ? '月度' : index % 3 === 1 ? '季度' : '年度'}盘点 ${index + 1}`,
      status,
      startTime: startDate.toLocaleString('zh-CN'),
      endTime: endDate ? endDate.toLocaleString('zh-CN') : null,
      checkedBy: checkers[Math.floor(Math.random() * checkers.length)],
      discrepancyCount: status === 'completed' ? Math.floor(Math.random() * 10) : 0,
      totalItems
    };
  });
};

// 模拟库存分类统计数据
const generateCategoryStats = (): CategoryStat[] => {
  const categories = ['电子产品', '服装鞋帽', '食品饮料', '家居用品', '其他'];
  
  return categories.map((category, index) => {
    const value = Math.floor(Math.random() * 1000) + 500;
    const lowStock = Math.floor(value * 0.15);
    const outOfStock = Math.floor(value * 0.05);
    const inStock = value - lowStock - outOfStock;
    
    return {
      name: category,
      value,
      inStock,
      lowStock,
      outOfStock
    };
  });
};

// 模拟库存趋势数据
const generateInventoryTrendData = () => {
  const months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月'];
  let inventory = 12000;
  
  return months.map(month => {
    const inQuantity = Math.floor(Math.random() * 2000) + 1000;
    const outQuantity = Math.floor(Math.random() * 2000) + 1000;
    inventory = Math.max(8000, inventory + inQuantity - outQuantity);
    
    return {
      month,
      inventory,
      in: inQuantity,
      out: outQuantity
    };
  });
};

// 渲染警报类型标签
const renderAlertTypeBadge = (type: string) => {
  switch (type) {
    case 'low-stock':
      return <span className="px-2 py-1 text-xs rounded-full bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200">库存不足</span>;
    case 'expiring-soon':
      return <span className="px-2 py-1 text-xs rounded-full bg-orange-100 dark:bg-orange-900 text-orange-800 dark:text-orange-200">即将过期</span>;
    case 'excess-stock':
      return <span className="px-2 py-1 text-xs rounded-full bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200">库存过剩</span>;
    default:
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">未知</span>;
  }
};

// 渲染警报状态标签
const renderAlertStatusBadge = (status: string) => {
  switch (status) {
    case 'pending':
      return <span className="px-2 py-1 text-xs rounded-full bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200">待处理</span>;
    case 'processed':
      return <span className="px-2 py-1 text-xs rounded-full bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200">已处理</span>;
    default:
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">未知</span>;
  }
};

// 渲染移动类型标签
const renderMovementTypeBadge = (type: string) => {
  switch (type) {
    case 'in':
      return <span className="px-2 py-1 text-xs rounded-full bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200">入库</span>;
    case 'out':
      return <span className="px-2 py-1 text-xs rounded-full bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200">出库</span>;
    case 'transfer':
      return <span className="px-2 py-1 text-xs rounded-full bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200">移库</span>;
    default:
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">未知</span>;
  }
};

// 渲染盘点状态标签
const renderCheckStatusBadge = (status: string) => {
  switch (status) {
    case 'pending':
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">待开始</span>;
    case 'in-progress':
      return <span className="px-2 py-1 text-xs rounded-full bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200">进行中</span>;
    case 'completed':
      return <span className="px-2 py-1 text-xs rounded-full bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200">已完成</span>;
    case 'cancelled':
      return <span className="px-2 py-1 text-xs rounded-full bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200">已取消</span>;
    default:
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">未知</span>;
  }
};

const InventoryManagement: React.FC = () => {
  const { theme } = useTheme();
  const [alerts, setAlerts] = useState<InventoryAlert[]>([]);
  const [filteredAlerts, setFilteredAlerts] = useState<InventoryAlert[]>([]);
  const [movements, setMovements] = useState<InventoryMovement[]>([]);
  const [filteredMovements, setFilteredMovements] = useState<InventoryMovement[]>([]);
  const [checks, setChecks] = useState<InventoryCheck[]>([]);
  const [categoryStats, setCategoryStats] = useState<CategoryStat[]>([]);
  const [inventoryTrend, setInventoryTrend] = useState(generateInventoryTrendData());
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedAlertType, setSelectedAlertType] = useState('all');
  const [selectedAlertStatus, setSelectedAlertStatus] = useState('all');
  const [selectedMovementType, setSelectedMovementType] = useState('all');
  const [isDetailModalOpen, setIsDetailModalOpen] = useState(false);
  const [isCheckModalOpen, setIsCheckModalOpen] = useState(false);
  const [currentAlert, setCurrentAlert] = useState<InventoryAlert | null>(null);
  const [currentMovement, setCurrentMovement] = useState<InventoryMovement | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage] = useState(10);
  const [isFilterDropdownOpen, setIsFilterDropdownOpen] = useState(false);
  const [activeTab, setActiveTab] = useState<'alerts' | 'movements' | 'checks'>('alerts');
  const [newCheck, setNewCheck] = useState<{
    name: string;
    startTime: string;
    checkedBy: string;
  }>({
    name: '',
    startTime: new Date().toLocaleString('zh-CN'),
    checkedBy: '管理员'
  });

  // 图表颜色
  const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884d8'];
  
  // 加载数据
  useEffect(() => {
    // 模拟API请求延迟
    const timer = setTimeout(() => {
      const mockAlertsData = generateMockAlerts();
      const mockMovementsData = generateMockMovements();
      const mockChecksData = generateMockChecks();
      const mockCategoryStatsData = generateCategoryStats();
      
      setAlerts(mockAlertsData);
      setFilteredAlerts(mockAlertsData);
      setMovements(mockMovementsData);
      setFilteredMovements(mockMovementsData);
      setChecks(mockChecksData);
      setCategoryStats(mockCategoryStatsData);
      setIsLoading(false);
    }, 1000);
    
    return () => clearTimeout(timer);
  }, []);
  
  // 搜索和筛选警报
  useEffect(() => {
    let result = [...alerts];
    
    // 搜索筛选
    if (searchTerm) {
      result = result.filter(item => 
        item.id.toLowerCase().includes(searchTerm.toLowerCase()) || 
        item.goodsId.toLowerCase().includes(searchTerm.toLowerCase()) ||
        item.goodsName.toLowerCase().includes(searchTerm.toLowerCase())
      );
    }
    
    // 警报类型筛选
    if (selectedAlertType !== 'all') {
      result = result.filter(item => item.alertType === selectedAlertType);
    }
    
    // 警报状态筛选
    if (selectedAlertStatus !== 'all') {
      result = result.filter(item => item.status === selectedAlertStatus);
    }
    
    setFilteredAlerts(result);
    setCurrentPage(1); // 重置到第一页
  }, [searchTerm, selectedAlertType, selectedAlertStatus, alerts, activeTab]);
  
  // 搜索和筛选移动记录
  useEffect(() => {
    let result = [...movements];
    
    // 搜索筛选
    if (searchTerm) {
      result = result.filter(item => 
        item.id.toLowerCase().includes(searchTerm.toLowerCase()) || 
        item.goodsId.toLowerCase().includes(searchTerm.toLowerCase()) ||
        item.goodsName.toLowerCase().includes(searchTerm.toLowerCase())
      );
    }
    
    // 移动类型筛选
    if (selectedMovementType !== 'all') {
      result = result.filter(item => item.movementType === selectedMovementType);
    }
    
    setFilteredMovements(result);
    setCurrentPage(1); // 重置到第一页
  }, [searchTerm, selectedMovementType, movements, activeTab]);
  
  // 分页功能
  const indexOfLastItem = currentPage * itemsPerPage;
  const indexOfFirstItem = indexOfLastItem - itemsPerPage;
  const currentItems = activeTab === 'alerts' 
    ? filteredAlerts.slice(indexOfFirstItem, indexOfLastItem)
    : activeTab === 'movements'
      ? filteredMovements.slice(indexOfFirstItem, indexOfLastItem)
      : checks.slice(indexOfFirstItem, indexOfLastItem);
  
  const totalPages = Math.ceil(
    activeTab === 'alerts' 
      ? filteredAlerts.length 
      : activeTab === 'movements'
        ? filteredMovements.length
        : checks.length
    / itemsPerPage
  );
  
  // 打开警报详情模态框
  const openAlertDetailModal = (alert: InventoryAlert) => {
    setCurrentAlert(alert);
    setIsDetailModalOpen(true);
  };
  
  // 打开移动记录详情模态框
  const openMovementDetailModal = (movement: InventoryMovement) => {
    setCurrentMovement(movement);
    setIsDetailModalOpen(true);
  };
  
  // 刷新数据
  const handleRefresh = () => {
    setIsLoading(true);
    // 模拟API请求延迟
    const timer = setTimeout(() => {
      const mockAlertsData = generateMockAlerts();
      const mockMovementsData = generateMockMovements();
      const mockChecksData = generateMockChecks();
      const mockCategoryStatsData = generateCategoryStats();
      const mockInventoryTrendData = generateInventoryTrendData();
      
      setAlerts(mockAlertsData);
      setFilteredAlerts(mockAlertsData);
      setMovements(mockMovementsData);
      setFilteredMovements(mockMovementsData);
      setChecks(mockChecksData);
      setCategoryStats(mockCategoryStatsData);
      setInventoryTrend(mockInventoryTrendData);
      setIsLoading(false);
      toast.success('数据刷新成功');
    }, 1000);
    
    return () => clearTimeout(timer);
  };
  
  // 处理警报标记为已处理
  const handleProcessAlert = (alertId: string) => {
    const updatedAlerts = alerts.map(alert => 
      alert.id === alertId ? { ...alert, status: 'processed' } : alert
    );
    setAlerts(updatedAlerts);
    toast.success('警报已标记为已处理');
  };
  
  // 处理创建新盘点任务
  const handleCreateCheck = () => {
    if (!newCheck.name || !newCheck.startTime || !newCheck.checkedBy) {
      toast.error('请填写完整的盘点信息');
      return;
    }
    
    const checkToAdd: InventoryCheck = {
      id: `CHECK-${String(checks.length + 1).padStart(4, '0')}`,
      name: newCheck.name,
      status: 'pending',
      startTime: newCheck.startTime,
      endTime: null,
      checkedBy: newCheck.checkedBy,
      discrepancyCount: 0,
      totalItems: Math.floor(Math.random() * 300) + 50
    };
    
    setChecks([checkToAdd, ...checks]);
    setIsCheckModalOpen(false);
    setNewCheck({
      name: '',
      startTime: new Date().toLocaleString('zh-CN'),
      checkedBy: '管理员'
    });
    toast.success('新盘点任务已创建');
  };
  
  // 分页控制
  const handlePageChange = (page: number) => {
    setCurrentPage(page);
  };
  
  // 获取统计数据
  const getInventoryStats = () => {
    const totalItems = categoryStats.reduce((sum, category) => sum + category.value, 0);
    const inStockItems = categoryStats.reduce((sum, category) => sum + category.inStock, 0);
    const lowStockItems = categoryStats.reduce((sum, category) => sum + category.lowStock, 0);
    const outOfStockItems = categoryStats.reduce((sum, category) => sum + category.outOfStock, 0);
    const pendingAlerts = alerts.filter(alert => alert.status === 'pending').length;
    
    return {
      totalItems,
      inStockItems,
      lowStockItems,
      outOfStockItems,
      pendingAlerts
    };
  };
  
  const stats = getInventoryStats();
  
  return (
    <div className="p-4 md:p-6">
      {/* 页面标题和操作区 */}
      <div className="flex flex-col md:flex-row justify-between items-start md:items-center mb-6">
        <div>
          <h2 className="text-2xl font-bold">库存管理</h2>
          <p className="text-gray-500 dark:text-gray-400">监控和管理仓库库存状态</p>
        </div>
        <div className="flex space-x-3 mt-4 md:mt-0">
          <button 
            onClick={handleRefresh}
            className="flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
          >
            <RefreshCw size={16} className="mr-2" />
            刷新
          </button>
          {activeTab === 'checks' && (
            <button 
              onClick={() => setIsCheckModalOpen(true)}
              className="flex items-center px-4 py-2 bg-blue-600 dark:bg-blue-700 text-white rounded-lg shadow-sm hover:bg-blue-700 dark:hover:bg-blue-800 transition-colors duration-200"
            >
              <Plus size={16} className="mr-2" />
              新建盘点
            </button>
          )}
        </div>
      </div>
      
      {/* 统计卡片 */}
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 mb-6">
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5 hover:shadow-md transition-shadow duration-300"
        >
          <div className="flex justify-between items-start">
            <div>
              <p className="text-gray-500 dark:text-gray-400 text-sm">库存总量</p>
              <h3 className="text-2xl font-bold mt-1">{stats.totalItems}</h3>
            </div>
            <div className="bg-blue-500 text-white p-2 rounded-lg">
              <Database size={20} />
            </div>
          </div>
        </motion.div>
        
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3, delay: 0.1 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5 hover:shadow-md transition-shadow duration-300"
        >
          <div className="flex justify-between items-start">
            <div>
              <p className="text-gray-500 dark:text-gray-400 text-sm">充足库存</p>
              <h3 className="text-2xl font-bold mt-1">{stats.inStockItems}</h3>
            </div>
            <div className="bg-green-500 text-white p-2 rounded-lg">
              <PackageCheck size={20} />
            </div>
          </div>
        </motion.div>
        
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3, delay: 0.2 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5 hover:shadow-md transition-shadow duration-300"
        >
          <div className="flex justify-between items-start">
            <div>
              <p className="text-gray-500 dark:text-gray-400 text-sm">库存不足</p>
              <h3 className="text-2xl font-bold mt-1">{stats.lowStockItems}</h3>
            </div>
            <div className="bg-yellow-500 text-white p-2 rounded-lg">
              <PackageOpen size={20} />
            </div>
          </div>
        </motion.div>
        
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3, delay: 0.3 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5 hover:shadow-md transition-shadow duration-300"
        >
          <div className="flex justify-between items-start">
            <div>
              <p className="text-gray-500 dark:text-gray-400 text-sm">缺货商品</p>
              <h3 className="text-2xl font-bold mt-1">{stats.outOfStockItems}</h3>
            </div>
            <div className="bg-red-500 text-white p-2 rounded-lg">
              <AlertCircle size={20} />
            </div>
          </div>
        </motion.div>
        
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3, delay: 0.4 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5 hover:shadow-md transition-shadow duration-300"
        >
          <div className="flex justify-between items-start">
            <div>
              <p className="text-gray-500 dark:text-gray-400 text-sm">待处理警报</p>
              <h3 className="text-2xl font-bold mt-1">{stats.pendingAlerts}</h3>
            </div>
            <div className="bg-purple-500 text-white p-2 rounded-lg">
              <AlertCircle size={20} />
            </div>
          </div>
        </motion.div>
      </div>
      
      {/* 标签切换 */}
      <div className="flex border-b border-gray-200 dark:border-gray-700 mb-6">
        <button
          onClick={() => setActiveTab('alerts')}
          className={`px-4 py-3 font-medium text-sm border-b-2 ${
            activeTab === 'alerts' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          库存警报
        </button>
        <button
          onClick={() => setActiveTab('movements')}
          className={`px-4 py-3 font-medium text-sm border-b-2 ${
            activeTab === 'movements' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          库存移动记录
        </button>
        <button
          onClick={() => setActiveTab('checks')}
          className={`px-4 py-3 font-medium text-sm border-b-2 ${
            activeTab === 'checks' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          库存盘点
        </button>
      </div>
      
      {/* 搜索和筛选区 */}
      <div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-4 mb-6">
        <div className="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4">
          <div className="relative flex-1">
            <Search size={18} className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" />
            <input
              type="text"
              placeholder={
                activeTab === 'alerts' 
                  ? "搜索警报ID、货物ID或名称..." 
                  : activeTab === 'movements'
                    ? "搜索记录ID、货物ID或名称..."
                    : "搜索盘点ID或名称..."
              }
              className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
            />
            {searchTerm && (
              <button 
                onClick={() => setSearchTerm('')}
                className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
              >
                <X size={16} />
              </button>
            )}
          </div>
          
          {(activeTab === 'alerts' || activeTab === 'movements') && (
            <div className="relative">
              <button
                onClick={() => setIsFilterDropdownOpen(!isFilterDropdownOpen)}
                className="flex items-center px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
              >
                <Filter size={16} className="mr-2" />
                筛选
                <ChevronDown size={16} className={`ml-2 transition-transform duration-200 ${isFilterDropdownOpen ? 'transform rotate-180' : ''}`} />
              </button>
              
              <AnimatePresence>
                {isFilterDropdownOpen && (
                  <motion.div
                    initial={{ opacity: 0, y: -10 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: -10 }}
                    transition={{ duration: 0.2 }}
                    className="absolute top-full left-0 mt-2 w-64 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-lg z-10 p-4"
                  >
                    {activeTab === 'alerts' && (
                      <>
                        <div className="mb-4">
                          <label className="block text-sm font-medium mb-2">警报类型</label>
                          <select
                            className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                            value={selectedAlertType}
                            onChange={(e) => setSelectedAlertType(e.target.value)}
                          >
                            <option value="all">全部类型</option>
                            <option value="low-stock">库存不足</option>
                            <option value="expiring-soon">即将过期</option>
                            <option value="excess-stock">库存过剩</option>
                          </select>
                        </div>
                        
                        <div>
                          <label className="block text-sm font-medium mb-2">警报状态</label>
                          <select
                            className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                            value={selectedAlertStatus}
                            onChange={(e) => setSelectedAlertStatus(e.target.value)}
                          >
                            <option value="all">全部状态</option>
                            <option value="pending">待处理</option>
                            <option value="processed">已处理</option>
                          </select>
                        </div>
                      </>
                    )}
                    
                    {activeTab === 'movements' && (
                      <div>
                        <label className="block text-sm font-medium mb-2">移动类型</label>
                        <select
                          className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                          value={selectedMovementType}
                          onChange={(e) => setSelectedMovementType(e.target.value)}
                        >
                          <option value="all">全部类型</option>
                          <option value="in">入库</option>
                          <option value="out">出库</option>
                          <option value="transfer">移库</option>
                        </select>
                      </div>
                    )}
                    
                    <div className="mt-4 flex justify-end">
                      <button
                        onClick={() => {
                          if (activeTab === 'alerts') {
                            setSelectedAlertType('all');
                            setSelectedAlertStatus('all');
                          } else if (activeTab === 'movements') {
                            setSelectedMovementType('all');
                          }
                          setIsFilterDropdownOpen(false);
                        }}
                        className="text-sm text-blue-600 dark:text-blue-400 hover:underline"
                      >
                        重置筛选
                      </button>
                    </div>
                  </motion.div>
                )}
              </AnimatePresence>
            </div>
          )}
        </div>
      </div>
      
      {/* 主要内容区域 */}
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
        {/* 列表区域 */}
        <div className="lg:col-span-2">
          <div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm overflow-hidden">
            <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
              <h3 className="font-bold text-lg">
                {activeTab === 'alerts' ? '库存警报列表' : activeTab === 'movements' ? '库存移动记录' : '库存盘点任务'}
              </h3>
              <div className="text-sm text-gray-500 dark:text-gray-400">
                {activeTab === 'alerts' 
                  ? `共 ${filteredAlerts.length} 条警报` 
                  : activeTab === 'movements'
                    ? `共 ${filteredMovements.length} 条记录`
                    : `共 ${checks.length} 个任务`
                }
              </div>
            </div>
            
            {isLoading ? (
              <div className="h-96 flex items-center justify-center">
                <div className="flex flex-col items-center">
                  <RefreshCw size={32} className="text-blue-500 animate-spin" />
                  <p className="mt-2 text-gray-500 dark:text-gray-400">加载中...</p>
                </div>
              </div>
            ) : (
              <div className="overflow-x-auto">
                <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
                  {activeTab === 'alerts' && (
                    <>
                      <thead>
                        <tr>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">ID</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">货物名称</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">分类</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">当前库存</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">预警阈值</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">位置</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">警报类型</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">状态</th>
                          <th className="px-4 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">操作</th>
                        </tr>
                      </thead>
                      <tbody className="divide-y divide-gray-200 dark:divide-gray-700">
                        {filteredAlerts.length === 0 ? (
                          <tr>
                            <td colSpan={9} className="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
                              没有找到匹配的警报
                            </td>
                          </tr>
                        ) : (
                          currentItems.map((alert) => (
                            <tr key={alert.id} className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200">
                              <td className="px-4 py-3 whitespace-nowrap text-sm font-medium">{alert.id}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{alert.goodsName}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{alert.category}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{alert.currentStock}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{alert.threshold}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{alert.location}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{renderAlertTypeBadge(alert.alertType)}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{renderAlertStatusBadge(alert.status)}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-right text-sm font-medium">
                                <div className="flex justify-end space-x-2">
                                  <button
                                    onClick={() => openAlertDetailModal(alert)}
                                    className="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300"
                                  >
                                    <Eye size={16} />
                                  </button>
                                  {alert.status === 'pending' && (
                                    <button
                                      onClick={() => handleProcessAlert(alert.id)}
                                      className="text-green-600 dark:text-green-400 hover:text-green-800 dark:hover:text-green-300"
                                    >
                                      <CheckCircle size={16} />
                                    </button>
                                  )}
                                </div>
                              </td>
                            </tr>
                          ))
                        )}
                      </tbody>
                    </>
                  )}
                  
                  {activeTab === 'movements' && (
                    <>
                      <thead>
                        <tr>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">ID</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">货物名称</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">移动类型</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">数量</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">从</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">到</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">操作人</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">时间</th>
                          <th className="px-4 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">操作</th>
                        </tr>
                      </thead>
                      <tbody className="divide-y divide-gray-200 dark:divide-gray-700">
                        {filteredMovements.length === 0 ? (
                          <tr>
                            <td colSpan={9} className="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
                              没有找到匹配的记录
                            </td>
                          </tr>
                        ) : (
                          currentItems.map((movement) => (
                            <tr key={movement.id} className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200">
                              <td className="px-4 py-3 whitespace-nowrap text-sm font-medium">{movement.id}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{movement.goodsName}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{renderMovementTypeBadge(movement.movementType)}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">
                                <div className="flex items-center">
                                  {movement.movementType === 'in' ? (
                                    <ArrowUp size={14} className="text-green-500 mr-1" />
                                  ) : movement.movementType === 'out' ? (
                                    <ArrowDown size={14} className="text-red-500 mr-1" />
                                  ) : (
                                    <MoveHorizontal size={14} className="text-blue-500 mr-1" />
                                  )}
                                  {movement.quantity}
                                </div>
                              </td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{movement.fromLocation}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{movement.toLocation}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{movement.operator}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{movement.movementTime}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-right text-sm font-medium">
                                <button
                                  onClick={() => openMovementDetailModal(movement)}
                                  className="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300"
                                >
                                  <Eye size={16} />
                                </button>
                              </td>
                            </tr>
                          ))
                        )}
                      </tbody>
                    </>
                  )}
                  
                  {activeTab === 'checks' && (
                    <>
                      <thead>
                        <tr>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">ID</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">名称</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">状态</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">开始时间</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">结束时间</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">盘点人</th>
                          <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">差异数</th>
                        </tr>
                      </thead>
                      <tbody className="divide-y divide-gray-200 dark:divide-gray-700">
                        {checks.length === 0 ? (
                          <tr>
                            <td colSpan={7} className="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
                              没有找到匹配的盘点任务
                            </td>
                          </tr>
                        ) : (
                          currentItems.map((check) => (
                            <tr key={check.id} className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200">
                              <td className="px-4 py-3 whitespace-nowrap text-sm font-medium">{check.id}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{check.name}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{renderCheckStatusBadge(check.status)}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{check.startTime}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{check.endTime || '-'}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{check.checkedBy}</td>
                              <td className="px-4 py-3 whitespace-nowrap text-sm">{check.discrepancyCount}</td>
                            </tr>
                          ))
                        )}
                      </tbody>
                    </>
                  )}
                </table>
              </div>
            )}
            
            {/* 分页控件 */}
            {(activeTab === 'alerts' && filteredAlerts.length > 0) || 
             (activeTab === 'movements' && filteredMovements.length > 0) ||
             (activeTab === 'checks' && checks.length > 0) ? (
              <div className="px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700">
                <div className="flex-1 flex justify-between sm:hidden">
                  <button
                    onClick={() => handlePageChange(currentPage - 1)}
                    disabled={currentPage === 1}
                    className={`relative inline-flex items-center px-4 py-2 border rounded-md text-sm font-medium ${
                      currentPage === 1 
                        ? 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-400 dark:text-gray-500 cursor-not-allowed' 
                        : 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'
                    }`}
                  >
                    上一页
                  </button>
                  <button
                    onClick={() => handlePageChange(currentPage + 1)}
                    disabled={currentPage === totalPages}
                    className={`ml-3 relative inline-flex items-center px-4 py-2 border rounded-md text-sm font-medium ${
                      currentPage === totalPages 
                        ? 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-400 dark:text-gray-500 cursor-not-allowed' 
                        : 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'
                    }`}
                  >
                    下一页
                  </button>
                </div>
                <div className="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
                  <div>
                    <p className="text-sm text-gray-700 dark:text-gray-300">
                      显示第 <span className="font-medium">{indexOfFirstItem + 1}</span> 到 <span className="font-medium">{Math.min(indexOfLastItem, 
                        activeTab === 'alerts' ? filteredAlerts.length : 
                        activeTab === 'movements' ? filteredMovements.length : checks.length)}</span> 条,共 <span className="font-medium">{
                        activeTab === 'alerts' ? filteredAlerts.length : 
                        activeTab === 'movements' ? filteredMovements.length : checks.length}</span> 条记录
                    </p>
                  </div>
                  <div>
                    <nav className="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
                      {[...Array(totalPages)].map((_, index) => {
                        // 只显示当前页、首页、末页以及前后各一页
                        if (
                          index === 0 || 
                          index === totalPages - 1 || 
                          Math.abs(index - (currentPage - 1)) <= 1
                        ) {
                          return (
                            <button
                              key={index}
                              onClick={() => handlePageChange(index + 1)}
                              className={`relative inline-flex items-center px-2 py-2 rounded-md text-sm font-medium ${
                                currentPage === index + 1
                                  ? 'bg-blue-50 dark:bg-blue-900 border-blue-300 dark:border-blue-700 text-blue-600 dark:text-blue-400'
                                  : 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'
                              }`}
                            >
                              {index + 1}
                            </button>
                          );
                        }
                        
                        // 添加省略号
                        if (
                          (index === 2 && currentPage > 4) ||
                          (index === totalPages - 3 && currentPage < totalPages - 3)
                        ) {
                          return (
                            <span key={index} className="relative inline-flex items-center px-2 py-2 rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-300">
                              ...
                            </span>
                          );
                        }
                        
                        return null;
                      })}
                    </nav>
                  </div>
                </div>
              </div>
            ) : null}
          </div>
        </div>
        
        {/* 数据分析区域 */}
        <div className="space-y-6">
          {/* 库存分类统计 */}
          <motion.div
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.3, delay: 0.2 }}
            className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5"
          >
            <h3 className="font-bold text-lg mb-4">库存分类统计</h3>
            <div className="h-64">
              <ResponsiveContainer width="100%" height="100%">
                <BarChart
                  data={categoryStats}
                  margin={{ top: 5, right: 5, left: 5, bottom: 40 }}
                >
                  <CartesianGrid strokeDasharray="3 3" stroke={theme === 'dark' ? '#374151' : '#e5e7eb'} />
                  <XAxis 
                    dataKey="name" 
                    stroke={theme === 'dark' ? '#9ca3af' : '#6b7280'}
                    angle={-45}
                    textAnchor="end"
                    height={60}
                  />
                  <YAxis stroke={theme === 'dark' ? '#9ca3af' : '#6b7280'} />
                  <Tooltip 
                    contentStyle={{ 
                      backgroundColor: theme === 'dark' ? '#1f2937' : '#ffffff',
                      border: `1px solid ${theme === 'dark' ? '#374151' : '#e5e7eb'}`,
                      color: theme === 'dark' ? '#ffffff' : '#000000'
                    }} 
                  />
                  <Legend />
                  <Bar dataKey="inStock" name="充足库存" stackId="a" fill="#10b981" />
                  <Bar dataKey="lowStock" name="库存不足" stackId="a" fill="#f59e0b" />
                  <Bar dataKey="outOfStock" name="缺货" stackId="a" fill="#ef4444" />
                </BarChart>
              </ResponsiveContainer>
            </div>
          </motion.div>
          
          {/* 库存趋势图 */}
          <motion.div
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.3, delay: 0.3 }}
            className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5"
          >
            <h3 className="font-bold text-lg mb-4">库存趋势</h3>
            <div className="h-64">
              <ResponsiveContainer width="100%" height="100%">
                <LineChart
                  data={inventoryTrend}
                  margin={{ top: 5, right: 5, left: 5, bottom: 20 }}
                >
                  <CartesianGrid strokeDasharray="3 3" stroke={theme === 'dark' ? '#374151' : '#e5e7eb'} />
                  <XAxis dataKey="month" stroke={theme === 'dark' ? '#9ca3af' : '#6b7280'} />
                  <YAxis yAxisId="left" stroke={theme === 'dark' ? '#9ca3af' : '#6b7280'} />
                  <YAxis yAxisId="right" orientation="right" stroke={theme === 'dark' ? '#9ca3af' : '#6b7280'} />
                  <Tooltip 
                    contentStyle={{ 
                      backgroundColor: theme === 'dark' ? '#1f2937' : '#ffffff',
                      border: `1px solid ${theme === 'dark' ? '#374151' : '#e5e7eb'}`,
                      color: theme === 'dark' ? '#ffffff' : '#000000'
                    }} 
                  />
                  <Legend />
                  <Line 
                    yAxisId="left"
                    type="monotone" 
                    dataKey="inventory" 
                    name="库存总量" 
                    stroke="#3b82f6" 
                    strokeWidth={2}
                    dot={{ r: 3 }}
                  />
                  <Line 
                    yAxisId="right"
                    type="monotone" 
                    dataKey="in" 
                    name="入库量" 
                    stroke="#10b981" 
                    strokeWidth={2}
                    dot={{ r: 3 }}
                  />
                  <Line 
                    yAxisId="right"
                    type="monotone" 
                    dataKey="out" 
                    name="出库量" 
                    stroke="#ef4444" 
                    strokeWidth={2}
                    dot={{ r: 3 }}
                  />
                </LineChart>
              </ResponsiveContainer>
            </div>
          </motion.div>
          
          {/* 库存状态饼图 */}
          <motion.div
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.3, delay: 0.4 }}
            className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5"
          >
            <h3 className="font-bold text-lg mb-4">库存状态分布</h3>
            <div className="h-64 flex justify-center">
              <ResponsiveContainer width="100%" height="100%">
                <PieChart>
                  <Pie
                    data={[
                      { name: '充足库存', value: stats.inStockItems },
                      { name: '库存不足', value: stats.lowStockItems },
                      { name: '缺货', value: stats.outOfStockItems }
                    ]}
                    cx="50%"
                    cy="50%"
                    innerRadius={60}
                    outerRadius={80}
                    fill="#8884d8"
                    paddingAngle={2}
                    dataKey="value"
                    label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`}
                    labelLine={false}
                  >
                    <Cell fill="#10b981" />
                    <Cell fill="#f59e0b" />
                    <Cell fill="#ef4444" />
                  </Pie>
                  <Tooltip 
                    contentStyle={{ 
                      backgroundColor: theme === 'dark' ? '#1f2937' : '#ffffff',
                      border: `1px solid ${theme === 'dark' ? '#374151' : '#e5e7eb'}`,
                      color: theme === 'dark' ? '#ffffff' : '#000000'
                    }} 
                  />
                </PieChart>
              </ResponsiveContainer>
            </div>
          </motion.div>
        </div>
      </div>
      
      {/* 详情模态框 */}
      <AnimatePresence>
        {isDetailModalOpen && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
            onClick={() => setIsDetailModalOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.9, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.9, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="bg-white dark:bg-gray-800 rounded-xl shadow-lg w-full max-w-lg max-h-[90vh] overflow-y-auto"
              onClick={(e) => e.stopPropagation()}
            >
              {currentAlert ? (
                <>
                  <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
                    <h3 className="font-bold text-lg">警报详情</h3>
                    <button onClick={() => setIsDetailModalOpen(false)} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
                      <X size={20} />
                    </button>
                  </div>
                  
                  <div className="p-5">
                    <div className="mb-6">
                      <div className="flex justify-center mb-4">
                        <div className="w-16 h-16 rounded-full bg-red-100 dark:bg-red-900 flex items-center justify-center text-red-600 dark:text-red-400">
                          <AlertCircle size={24} />
                        </div>
                      </div>
                      <h4 className="text-xl font-bold text-center">{currentAlert.goodsName}</h4>
                      <p className="text-center text-gray-500 dark:text-gray-400">{currentAlert.id}</p>
                    </div>
                    
                    <div className="space-y-4">
                      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">货物ID</p>
                          <p className="font-medium">{currentAlert.goodsId}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">货物分类</p>
                          <p className="font-medium">{currentAlert.category}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">当前库存</p>
                          <p className="font-medium">{currentAlert.currentStock}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">预警阈值</p>
                          <p className="font-medium">{currentAlert.threshold}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">存放位置</p>
                          <p className="font-medium">{currentAlert.location}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">警报类型</p>
                          <p className="font-medium">{renderAlertTypeBadge(currentAlert.alertType)}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">警报状态</p>
                          <p className="font-medium">{renderAlertStatusBadge(currentAlert.status)}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">警报时间</p>
                          <p className="font-medium">{currentAlert.alertTime}</p>
                        </div>
                      </div>
                    </div>
                  </div>
                  
                  <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-end">
                    {currentAlert.status === 'pending' && (
                      <button
                        onClick={() => {
                          handleProcessAlert(currentAlert.id);
                          setIsDetailModalOpen(false);
                        }}
                        className="mr-3 px-4 py-2 bg-green-600 dark:bg-green-700 text-white rounded-lg shadow-sm hover:bg-green-700 dark:hover:bg-green-800 transition-colors duration-200"
                      >
                        标记为已处理
                      </button>
                    )}
                    <button
                      onClick={() => setIsDetailModalOpen(false)}
                      className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                    >
                      关闭
                    </button>
                  </div>
                </>
              ) : currentMovement ? (
                <>
                  <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
                    <h3 className="font-bold text-lg">移动记录详情</h3>
                    <button onClick={() => setIsDetailModalOpen(false)} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
                      <X size={20} />
                    </button>
                  </div>
                  
                  <div className="p-5">
                    <div className="mb-6">
                      <div className="flex justify-center mb-4">
                        <div className="w-16 h-16 rounded-full bg-blue-100 dark:bg-blue-900 flex items-center justify-center text-blue-600 dark:text-blue-400"><MoveHorizontal size={24} />
                        </div>
                      </div>
                      <h4 className="text-xl font-bold text-center">{currentMovement.goodsName}</h4>
                      <p className="text-center text-gray-500 dark:text-gray-400">{currentMovement.id}</p>
                    </div>
                    
                    <div className="space-y-4">
                      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">货物ID</p>
                          <p className="font-medium">{currentMovement.goodsId}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">移动类型</p>
                          <p className="font-medium">{renderMovementTypeBadge(currentMovement.movementType)}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">移动数量</p>
                          <p className="font-medium">{currentMovement.quantity}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">操作人</p>
                          <p className="font-medium">{currentMovement.operator}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">起始位置</p>
                          <p className="font-medium">{currentMovement.fromLocation}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">目标位置</p>
                          <p className="font-medium">{currentMovement.toLocation}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">移动时间</p>
                          <p className="font-medium">{currentMovement.movementTime}</p>
                        </div>
                        
                        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                          <p className="text-sm text-gray-500 dark:text-gray-400">移动原因</p>
                          <p className="font-medium">{currentMovement.reason}</p>
                        </div>
                      </div>
                    </div>
                  </div>
                  
                  <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-end">
                    <button
                      onClick={() => setIsDetailModalOpen(false)}
                      className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                    >
                      关闭
                    </button>
                  </div>
                </>
              ) : null}
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
      
      {/* 创建盘点任务模态框 */}
      <AnimatePresence>
        {isCheckModalOpen && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
            onClick={() => setIsCheckModalOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.9, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.9, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="bg-white dark:bg-gray-800 rounded-xl shadow-lg w-full max-w-md max-h-[90vh] overflow-y-auto"
              onClick={(e) => e.stopPropagation()}
            >
              <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
                <h3 className="font-bold text-lg">新建盘点任务</h3>
                <button onClick={() => setIsCheckModalOpen(false)} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
                  <X size={20} />
                </button>
              </div>
              
              <div className="p-5">
                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-medium mb-2">盘点名称 <span className="text-red-500">*</span></label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newCheck.name}
                      onChange={(e) => setNewCheck({ ...newCheck, name: e.target.value })}
                      placeholder="例如:月度盘点"
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">开始时间 <span className="text-red-500">*</span></label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newCheck.startTime}
                      onChange={(e) => setNewCheck({ ...newCheck, startTime: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">盘点人 <span className="text-red-500">*</span></label>
                    <select
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newCheck.checkedBy}
                      onChange={(e) => setNewCheck({ ...newCheck, checkedBy: e.target.value })}
                    >
                      <option value="管理员">管理员</option>
                      <option value="操作员A">操作员A</option>
                      <option value="操作员B">操作员B</option>
                      <option value="操作员C">操作员C</option>
                    </select>
                  </div>
                </div>
              </div>
              
              <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
                <button
                  onClick={() => setIsCheckModalOpen(false)}
                  className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                >
                  取消
                </button>
                <button
                  onClick={handleCreateCheck}
                  className="px-4 py-2 bg-blue-600 dark:bg-blue-700 text-white rounded-lg shadow-sm hover:bg-blue-700 dark:hover:bg-blue-800 transition-colors duration-200"
                >
                  创建
                </button>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

export default InventoryManagement;
UserManagement.tsx #用户管理:
bash 复制代码
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { 
  Users, Search, Plus, Edit, Trash2, Eye, Filter, X, 
  CheckCircle, AlertCircle, ChevronDown, RefreshCw, 
  UserPlus, Lock, Unlock, UserX, UserCheck
} from 'lucide-react';
import { useTheme } from '@/hooks/useTheme';
import { toast } from 'sonner';

// 用户数据类型定义
interface User {
  id: string;
  username: string;
  realName: string;
  email: string;
  phone: string;
  role: 'admin' | 'operator' | 'viewer';
  status: 'active' | 'inactive' | 'locked';
  createdAt: string;
  lastLogin: string;
  permissions: {
    canManageGoods: boolean;
    canManageRobots: boolean;
    canManageInventory: boolean;
    canManageUsers: boolean;
    canViewAnalytics: boolean;
    canManageSettings: boolean;
  };
}

// 模拟用户数据
const generateMockUsers = (): User[] => {
  const roles: Array<'admin' | 'operator' | 'viewer'> = ['admin', 'operator', 'viewer'];
  const statuses: Array<'active' | 'inactive' | 'locked'> = ['active', 'inactive', 'locked'];
  
  return Array.from({ length: 20 }, (_, index) => {
    const role = roles[Math.floor(Math.random() * roles.length)];
    const status = statuses[Math.floor(Math.random() * statuses.length)];
    const createDate = new Date(Date.now() - Math.floor(Math.random() * 365) * 24 * 60 * 60 * 1000);
    const lastLoginDate = status === 'active' 
      ? new Date(createDate.getTime() + Math.floor(Math.random() * 180) * 24 * 60 * 60 * 1000)
      : null;
    
    // 基于角色设置权限
    const basePermissions = {
      canManageGoods: false,
      canManageRobots: false,
      canManageInventory: false,
      canManageUsers: false,
      canViewAnalytics: false,
      canManageSettings: false
    };
    
    let permissions = { ...basePermissions };
    
    if (role === 'admin') {
      permissions = {
        canManageGoods: true,
        canManageRobots: true,
        canManageInventory: true,
        canManageUsers: true,
        canViewAnalytics: true,
        canManageSettings: true
      };
    } else if (role === 'operator') {
      permissions = {
        canManageGoods: true,
        canManageRobots: true,
        canManageInventory: true,
        canManageUsers: false,
        canViewAnalytics: true,
        canManageSettings: false
      };
    } else if (role === 'viewer') {
      permissions = {
        canManageGoods: false,
        canManageRobots: false,
        canManageInventory: false,
        canManageUsers: false,
        canViewAnalytics: true,
        canManageSettings: false
      };
    }
    
    return {
      id: `USER-${String(index + 1).padStart(4, '0')}`,
      username: `user${index + 1}`,
      realName: `用户${index + 1}`,
      email: `user${index + 1}@example.com`,
      phone: `138${String(Math.floor(Math.random() * 100000000)).padStart(8, '0')}`,
      role,
      status,
      createdAt: createDate.toLocaleDateString('zh-CN'),
      lastLogin: lastLoginDate ? lastLoginDate.toLocaleString('zh-CN') : '-',
      permissions
    };
  });
};

// 渲染角色标签
const renderRoleBadge = (role: string) => {
  switch (role) {
    case 'admin':
      return <span className="px-2 py-1 text-xs rounded-full bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200">管理员</span>;
    case 'operator':
      return <span className="px-2 py-1 text-xs rounded-full bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200">操作员</span>;
    case 'viewer':
      return <span className="px-2 py-1 text-xs rounded-full bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200">查看者</span>;
    default:
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">未知</span>;
  }
};

// 渲染状态标签
const renderStatusBadge = (status: string) => {
  switch (status) {
    case 'active':
      return <span className="px-2 py-1 text-xs rounded-full bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200">活跃</span>;
    case 'inactive':
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">未激活</span>;
    case 'locked':
      return <span className="px-2 py-1 text-xs rounded-full bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200">已锁定</span>;
    default:
      return <span className="px-2 py-1 text-xs rounded-full bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200">未知</span>;
  }
};

// 渲染权限状态
const renderPermissionStatus = (hasPermission: boolean) => {
  return hasPermission ? (
    <CheckCircle size={18} className="text-green-500" />
  ) : (
    <X size={18} className="text-red-500" />
  );
};

const UserManagement: React.FC = () => {
  const { theme } = useTheme();
  const [users, setUsers] = useState<User[]>([]);
  const [filteredUsers, setFilteredUsers] = useState<User[]>([]);
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedRole, setSelectedRole] = useState('all');
  const [selectedStatus, setSelectedStatus] = useState('all');
  const [isAddModalOpen, setIsAddModalOpen] = useState(false);
  const [isEditModalOpen, setIsEditModalOpen] = useState(false);
  const [isDetailModalOpen, setIsDetailModalOpen] = useState(false);
  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
  const [currentUser, setCurrentUser] = useState<User | null>(null);
  const [newUser, setNewUser] = useState<Partial<User>>({
    username: '',
    realName: '',
    email: '',
    phone: '',
    role: 'viewer',
    status: 'active',
    permissions: {
      canManageGoods: false,
      canManageRobots: false,
      canManageInventory: false,
      canManageUsers: false,
      canViewAnalytics: false,
      canManageSettings: false
    }
  });
  const [isLoading, setIsLoading] = useState(true);
  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage] = useState(10);
  const [isFilterDropdownOpen, setIsFilterDropdownOpen] = useState(false);

  // 加载用户数据
  useEffect(() => {
    // 模拟API请求延迟
    const timer = setTimeout(() => {
      const mockData = generateMockUsers();
      setUsers(mockData);
      setFilteredUsers(mockData);
      setIsLoading(false);
    }, 1000);
    
    return () => clearTimeout(timer);
  }, []);
  
  // 搜索和筛选功能
  useEffect(() => {
    let result = [...users];
    
    // 搜索筛选
    if (searchTerm) {
      result = result.filter(item => 
        item.id.toLowerCase().includes(searchTerm.toLowerCase()) || 
        item.username.toLowerCase().includes(searchTerm.toLowerCase()) ||
        item.realName.toLowerCase().includes(searchTerm.toLowerCase()) ||
        item.email.toLowerCase().includes(searchTerm.toLowerCase())
      );
    }
    
    // 角色筛选
    if (selectedRole !== 'all') {
      result = result.filter(item => item.role === selectedRole);
    }
    
    // 状态筛选
    if (selectedStatus !== 'all') {
      result = result.filter(item => item.status === selectedStatus);
    }
    
    setFilteredUsers(result);
    setCurrentPage(1); // 重置到第一页
  }, [searchTerm, selectedRole, selectedStatus, users]);
  
  // 分页功能
  const indexOfLastItem = currentPage * itemsPerPage;
  const indexOfFirstItem = indexOfLastItem - itemsPerPage;
  const currentItems = filteredUsers.slice(indexOfFirstItem, indexOfLastItem);
  const totalPages = Math.ceil(filteredUsers.length / itemsPerPage);
  
  // 处理添加用户
  const handleAddUser = () => {
    if (!newUser.username || !newUser.realName || !newUser.email) {
      toast.error('请填写必要的用户信息');
      return;
    }
    
    const userToAdd: User = {
      id: `USER-${String(users.length + 1).padStart(4, '0')}`,
      username: newUser.username!,
      realName: newUser.realName!,
      email: newUser.email!,
      phone: newUser.phone || '',
      role: newUser.role || 'viewer',
      status: newUser.status || 'active',
      createdAt: new Date().toLocaleDateString('zh-CN'),
      lastLogin: '-',
      permissions: newUser.permissions || {
        canManageGoods: false,
        canManageRobots: false,
        canManageInventory: false,
        canManageUsers: false,
        canViewAnalytics: false,
        canManageSettings: false
      }
    };
    
    setUsers([...users, userToAdd]);
    setIsAddModalOpen(false);
    setNewUser({
      username: '',
      realName: '',
      email: '',
      phone: '',
      role: 'viewer',
      status: 'active',
      permissions: {
        canManageGoods: false,
        canManageRobots: false,
        canManageInventory: false,
        canManageUsers: false,
        canViewAnalytics: false,
        canManageSettings: false
      }
    });
    toast.success('用户添加成功');
  };
  
  // 处理编辑用户
  const handleEditUser = () => {
    if (!currentUser) return;
    
    const updatedUsers = users.map(user => 
      user.id === currentUser.id ? currentUser : user
    );
    
    setUsers(updatedUsers);
    setIsEditModalOpen(false);
    setCurrentUser(null);
    toast.success('用户信息更新成功');
  };
  
  // 处理删除用户
  const handleDeleteUser = () => {
    if (!currentUser) return;
    
    const updatedUsers = users.filter(user => user.id !== currentUser.id);
    setUsers(updatedUsers);
    setIsDeleteModalOpen(false);
    setCurrentUser(null);
    toast.success('用户删除成功');
  };
  
  // 处理用户状态变更
  const handleStatusChange = (userId: string, newStatus: 'active' | 'inactive' | 'locked') => {
    const updatedUsers = users.map(user => 
      user.id === userId ? { ...user, status: newStatus } : user
    );
    setUsers(updatedUsers);
    toast.success('用户状态已更新');
  };
  
  // 打开编辑模态框
  const openEditModal = (user: User) => {
    setCurrentUser({ ...user });
    setIsEditModalOpen(true);
  };
  
  // 打开详情模态框
  const openDetailModal = (user: User) => {
    setCurrentUser({ ...user });
    setIsDetailModalOpen(true);
  };
  
  // 打开删除确认模态框
  const openDeleteModal = (user: User) => {
    setCurrentUser({ ...user });
    setIsDeleteModalOpen(true);
  };
  
  // 刷新数据
  const handleRefresh = () => {
    setIsLoading(true);
    // 模拟API请求延迟
    const timer = setTimeout(() => {
      const mockData = generateMockUsers();
      setUsers(mockData);
      setFilteredUsers(mockData);
      setIsLoading(false);
      toast.success('数据刷新成功');
    }, 1000);
    
    return () => clearTimeout(timer);
  };
  
  // 分页控制
  const handlePageChange = (page: number) => {
    setCurrentPage(page);
  };
  
  // 根据角色更新权限
  const handleRoleChange = (role: 'admin' | 'operator' | 'viewer') => {
    if (isAddModalOpen) {
      let newPermissions = {
        canManageGoods: false,
        canManageRobots: false,
        canManageInventory: false,
        canManageUsers: false,
        canViewAnalytics: false,
        canManageSettings: false
      };
      
      if (role === 'admin') {
        newPermissions = {
          canManageGoods: true,
          canManageRobots: true,
          canManageInventory: true,
          canManageUsers: true,
          canViewAnalytics: true,
          canManageSettings: true
        };
      } else if (role === 'operator') {
        newPermissions = {
          canManageGoods: true,
          canManageRobots: true,
          canManageInventory: true,
          canManageUsers: false,
          canViewAnalytics: true,
          canManageSettings: false};
      } else if (role === 'viewer') {
        newPermissions = {
          canManageGoods: false,
          canManageRobots: false,
          canManageInventory: false,
          canManageUsers: false,
          canViewAnalytics: true,
          canManageSettings: false
        };
      }
      
      setNewUser({
        ...newUser,
        role,
        permissions: newPermissions
      });
    } else if (isEditModalOpen && currentUser) {
      let newPermissions = {
        canManageGoods: false,
        canManageRobots: false,
        canManageInventory: false,
        canManageUsers: false,
        canViewAnalytics: false,
        canManageSettings: false
      };
      
      if (role === 'admin') {
        newPermissions = {
          canManageGoods: true,
          canManageRobots: true,
          canManageInventory: true,
          canManageUsers: true,
          canViewAnalytics: true,
          canManageSettings: true
        };
      } else if (role === 'operator') {
        newPermissions = {
          canManageGoods: true,
          canManageRobots: true,
          canManageInventory: true,
          canManageUsers: false,
          canViewAnalytics: true,
          canManageSettings: false
        };
      } else if (role === 'viewer') {
        newPermissions = {
          canManageGoods: false,
          canManageRobots: false,
          canManageInventory: false,
          canManageUsers: false,
          canViewAnalytics: true,
          canManageSettings: false
        };
      }
      
      setCurrentUser({
        ...currentUser,
        role,
        permissions: newPermissions
      });
    }
  };

  return (
    <div className="p-4 md:p-6">
      {/* 页面标题和操作区 */}
      <div className="flex flex-col md:flex-row justify-between items-start md:items-center mb-6">
        <div>
          <h2 className="text-2xl font-bold">用户管理</h2>
          <p className="text-gray-500 dark:text-gray-400">管理系统用户和权限</p>
        </div>
        <div className="flex space-x-3 mt-4 md:mt-0">
          <button 
            onClick={handleRefresh}
            className="flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
          >
            <RefreshCw size={16} className="mr-2" />
            刷新
          </button>
          <button 
            onClick={() => setIsAddModalOpen(true)}
            className="flex items-center px-4 py-2 bg-blue-600 dark:bg-blue-700 text-white rounded-lg shadow-sm hover:bg-blue-700 dark:hover:bg-blue-800 transition-colors duration-200"
          >
            <Plus size={16} className="mr-2" />
            添加用户
          </button>
        </div>
      </div>
      
      {/* 搜索和筛选区 */}
      <div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-4 mb-6">
        <div className="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4">
          <div className="relative flex-1">
            <Search size={18} className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" />
            <input
              type="text"
              placeholder="搜索用户ID、用户名、姓名或邮箱..."
              className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
            />
            {searchTerm && (
              <button 
                onClick={() => setSearchTerm('')}
                className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
              >
                <X size={16} />
              </button>
            )}
          </div>
          
          <div className="relative">
            <button
              onClick={() => setIsFilterDropdownOpen(!isFilterDropdownOpen)}
              className="flex items-center px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
            >
              <Filter size={16} className="mr-2" />
              筛选
              <ChevronDown size={16} className={`ml-2 transition-transform duration-200 ${isFilterDropdownOpen ? 'transform rotate-180' : ''}`} />
            </button>
            
            <AnimatePresence>
              {isFilterDropdownOpen && (
                <motion.div
                  initial={{ opacity: 0, y: -10 }}
                  animate={{ opacity: 1, y: 0 }}
                  exit={{ opacity: 0, y: -10 }}
                  transition={{ duration: 0.2 }}
                  className="absolute top-full left-0 mt-2 w-64 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-lg z-10 p-4"
                >
                  <div className="mb-4">
                    <label className="block text-sm font-medium mb-2">用户角色</label>
                    <select
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={selectedRole}
                      onChange={(e) => setSelectedRole(e.target.value)}
                    >
                      <option value="all">全部角色</option>
                      <option value="admin">管理员</option>
                      <option value="operator">操作员</option>
                      <option value="viewer">查看者</option>
                    </select>
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">用户状态</label>
                    <select
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={selectedStatus}
                      onChange={(e) => setSelectedStatus(e.target.value)}
                    >
                      <option value="all">全部状态</option>
                      <option value="active">活跃</option>
                      <option value="inactive">未激活</option>
                      <option value="locked">已锁定</option>
                    </select>
                  </div>
                  
                  <div className="mt-4 flex justify-end">
                    <button
                      onClick={() => {
                        setSelectedRole('all');
                        setSelectedStatus('all');
                        setIsFilterDropdownOpen(false);
                      }}
                      className="text-sm text-blue-600 dark:text-blue-400 hover:underline"
                    >
                      重置筛选
                    </button>
                  </div>
                </motion.div>
              )}
            </AnimatePresence>
          </div>
        </div>
      </div>
      
      {/* 用户列表 */}
      <div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm overflow-hidden mb-6">
        <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
          <h3 className="font-bold text-lg">用户列表</h3>
          <div className="text-sm text-gray-500 dark:text-gray-400">
            共 {filteredUsers.length} 个用户
          </div>
        </div>
        
        {isLoading ? (
          <div className="h-96 flex items-center justify-center">
            <div className="flex flex-col items-center">
              <RefreshCw size={32} className="text-blue-500 animate-spin" />
              <p className="mt-2 text-gray-500 dark:text-gray-400">加载中...</p>
            </div>
          </div>
        ) : filteredUsers.length === 0 ? (
          <div className="h-96 flex items-center justify-center">
            <div className="text-center">
              <Users size={48} className="mx-auto text-gray-300 dark:text-gray-600 mb-2" />
              <p className="text-gray-500 dark:text-gray-400">没有找到匹配的用户</p>
              <button 
                onClick={() => {
                  setSearchTerm('');
                  setSelectedRole('all');
                  setSelectedStatus('all');
                }}
                className="mt-2 text-sm text-blue-600 dark:text-blue-400 hover:underline"
              >
                清除筛选条件
              </button>
            </div>
          </div>
        ) : (
          <>
            <div className="overflow-x-auto">
              <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
                <thead>
                  <tr>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">ID</th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">用户名</th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">姓名</th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">邮箱</th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">角色</th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">状态</th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">创建日期</th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">最后登录</th>
                    <th className="px-4 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">操作</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-gray-200 dark:divide-gray-700">
                  {currentItems.map((user) => (
                    <tr key={user.id} className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200">
                      <td className="px-4 py-3 whitespace-nowrap text-sm font-medium">{user.id}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-sm">{user.username}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-sm">{user.realName}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-sm">{user.email}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-sm">{renderRoleBadge(user.role)}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-sm">{renderStatusBadge(user.status)}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-sm">{user.createdAt}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-sm">{user.lastLogin}</td>
                      <td className="px-4 py-3 whitespace-nowrap text-right text-sm font-medium">
                        <div className="flex justify-end space-x-2">
                          <button
                            onClick={() => openDetailModal(user)}
                            className="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300"
                          >
                            <Eye size={16} />
                          </button>
                          <button
                            onClick={() => openEditModal(user)}
                            className="text-green-600 dark:text-green-400 hover:text-green-800 dark:hover:text-green-300"
                          >
                            <Edit size={16} />
                          </button>
                          <button
                            onClick={() => openDeleteModal(user)}
                            className="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300"
                          >
                            <Trash2 size={16} />
                          </button>
                        </div>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            
            {/* 分页控件 */}
            <div className="px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700">
              <div className="flex-1 flex justify-between sm:hidden">
                <button
                  onClick={() => handlePageChange(currentPage - 1)}
                  disabled={currentPage === 1}
                  className={`relative inline-flex items-center px-4 py-2 border rounded-md text-sm font-medium ${
                    currentPage === 1 
                      ? 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-400 dark:text-gray-500 cursor-not-allowed' 
                      : 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'
                  }`}
                >
                  上一页
                </button>
                <button
                  onClick={() => handlePageChange(currentPage + 1)}
                  disabled={currentPage === totalPages}
                  className={`ml-3 relative inline-flex items-center px-4 py-2 border rounded-md text-sm font-medium ${
                    currentPage === totalPages 
                      ? 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-400 dark:text-gray-500 cursor-not-allowed' 
                      : 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'
                  }`}
                >
                  下一页
                </button>
              </div>
              <div className="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
                <div>
                  <p className="text-sm text-gray-700 dark:text-gray-300">
                    显示第 <span className="font-medium">{indexOfFirstItem + 1}</span> 到 <span className="font-medium">{Math.min(indexOfLastItem, filteredUsers.length)}</span> 条,共 <span className="font-medium">{filteredUsers.length}</span> 条记录
                  </p>
                </div>
                <div>
                  <nav className="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
                    {[...Array(totalPages)].map((_, index) => {
                      // 只显示当前页、首页、末页以及前后各一页
                      if (
                        index === 0 || 
                        index === totalPages - 1 || 
                        Math.abs(index - (currentPage - 1)) <= 1
                      ) {
                        return (
                          <button
                            key={index}
                            onClick={() => handlePageChange(index + 1)}
                            className={`relative inline-flex items-center px-2 py-2 rounded-md text-sm font-medium ${
                              currentPage === index + 1
                                ? 'bg-blue-50 dark:bg-blue-900 border-blue-300 dark:border-blue-700 text-blue-600 dark:text-blue-400'
                                : 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'
                            }`}
                          >
                            {index + 1}
                          </button>
                        );
                      }
                      
                      // 添加省略号
                      if (
                        (index === 2 && currentPage > 4) ||
                        (index === totalPages - 3 && currentPage < totalPages - 3)
                      ) {
                        return (
                          <span key={index} className="relative inline-flex items-center px-2 py-2 rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-300">
                            ...
                          </span>
                        );
                      }
                      
                      return null;
                    })}
                  </nav>
                </div>
              </div>
            </div>
          </>
        )}
      </div>
      
      {/* 添加用户模态框 */}
      <AnimatePresence>
        {isAddModalOpen && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
            onClick={() => setIsAddModalOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.9, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.9, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="bg-white dark:bg-gray-800 rounded-xl shadow-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto"
              onClick={(e) => e.stopPropagation()}
            >
              <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
                <h3 className="font-bold text-lg">添加新用户</h3>
                <button onClick={() => setIsAddModalOpen(false)} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
                  <X size={20} />
                </button>
              </div>
              
              <div className="p-5">
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  <div>
                    <label className="block text-sm font-medium mb-2">用户名 <span className="text-red-500">*</span></label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newUser.username || ''}
                      onChange={(e) => setNewUser({ ...newUser, username: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">姓名 <span className="text-red-500">*</span></label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newUser.realName || ''}
                      onChange={(e) => setNewUser({ ...newUser, realName: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">邮箱 <span className="text-red-500">*</span></label>
                    <input
                      type="email"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newUser.email || ''}
                      onChange={(e) => setNewUser({ ...newUser, email: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">电话</label>
                    <input
                      type="tel"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newUser.phone || ''}
                      onChange={(e) => setNewUser({ ...newUser, phone: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">角色 <span className="text-red-500">*</span></label>
                    <select
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newUser.role || 'viewer'}
                      onChange={(e) => handleRoleChange(e.target.value as 'admin' | 'operator' | 'viewer')}
                    >
                      <option value="admin">管理员</option>
                      <option value="operator">操作员</option>
                      <option value="viewer">查看者</option>
                    </select>
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">状态</label>
                    <select
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={newUser.status || 'active'}
                      onChange={(e) => setNewUser({ ...newUser, status: e.target.value as 'active' | 'inactive' | 'locked' })}
                    >
                      <option value="active">活跃</option>
                      <option value="inactive">未激活</option>
                      <option value="locked">已锁定</option>
                    </select>
                  </div>
                </div>
                
                <div className="mt-6">
                  <label className="block text-sm font-medium mb-3">权限设置</label>
                  <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="canManageGoods"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={newUser.permissions?.canManageGoods || false}
                        onChange={(e) => setNewUser({
                          ...newUser,
                          permissions: {
                            ...(newUser.permissions || {}),
                            canManageGoods: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="canManageGoods" className="ml-2 block text-sm">管理货物</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="canManageRobots"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={newUser.permissions?.canManageRobots || false}
                        onChange={(e) => setNewUser({
                          ...newUser,
                          permissions: {
                            ...(newUser.permissions || {}),
                            canManageRobots: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="canManageRobots" className="ml-2 block text-sm">管理机器人</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="canManageInventory"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={newUser.permissions?.canManageInventory || false}
                        onChange={(e) => setNewUser({
                          ...newUser,
                          permissions: {
                            ...(newUser.permissions || {}),
                            canManageInventory: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="canManageInventory" className="ml-2 block text-sm">管理库存</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="canManageUsers"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={newUser.permissions?.canManageUsers || false}
                        onChange={(e) => setNewUser({
                          ...newUser,
                          permissions: {
                            ...(newUser.permissions || {}),
                            canManageUsers: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="canManageUsers" className="ml-2 block text-sm">管理用户</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="canViewAnalytics"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={newUser.permissions?.canViewAnalytics || false}
                        onChange={(e) => setNewUser({
                          ...newUser,
                          permissions: {
                            ...(newUser.permissions || {}),
                            canViewAnalytics: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="canViewAnalytics" className="ml-2 block text-sm">查看分析</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="canManageSettings"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={newUser.permissions?.canManageSettings || false}
                        onChange={(e) => setNewUser({
                          ...newUser,
                          permissions: {
                            ...(newUser.permissions || {}),
                            canManageSettings: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="canManageSettings" className="ml-2 block text-sm">管理设置</label>
                    </div>
                  </div>
                </div>
              </div>
              
              <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
                <button
                  onClick={() => setIsAddModalOpen(false)}
                  className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                >
                  取消
                </button>
                <button
                  onClick={handleAddUser}
                  className="px-4 py-2 bg-blue-600 dark:bg-blue-700 text-white rounded-lg shadow-sm hover:bg-blue-700 dark:hover:bg-blue-800 transition-colors duration-200"
                >
                  添加
                </button>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
      
      {/* 编辑用户模态框 */}
      <AnimatePresence>
        {isEditModalOpen && currentUser && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
            onClick={() => setIsEditModalOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.9, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.9, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="bg-white dark:bg-gray-800 rounded-xl shadow-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto"
              onClick={(e) => e.stopPropagation()}
            >
              <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
                <h3 className="font-bold text-lg">编辑用户</h3>
                <button onClick={() => setIsEditModalOpen(false)} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
                  <X size={20} />
                </button>
              </div>
              
              <div className="p-5">
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  <div>
                    <label className="block text-sm font-medium mb-2">用户ID</label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-100 dark:bg-gray-900 text-gray-500 dark:text-gray-400 cursor-not-allowed"
                      value={currentUser.id}
                      disabled
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">用户名 <span className="text-red-500">*</span></label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={currentUser.username}
                      onChange={(e) => setCurrentUser({ ...currentUser, username: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">姓名 <span className="text-red-500">*</span></label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={currentUser.realName}
                      onChange={(e) => setCurrentUser({ ...currentUser, realName: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">邮箱 <span className="text-red-500">*</span></label>
                    <input
                      type="email"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={currentUser.email}
                      onChange={(e) => setCurrentUser({ ...currentUser, email: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">电话</label>
                    <input
                      type="tel"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={currentUser.phone}
                      onChange={(e) => setCurrentUser({ ...currentUser, phone: e.target.value })}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">角色 <span className="text-red-500">*</span></label>
                    <select
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={currentUser.role}
                      onChange={(e) => handleRoleChange(e.target.value as 'admin' | 'operator' | 'viewer')}
                    >
                      <option value="admin">管理员</option>
                      <option value="operator">操作员</option>
                      <option value="viewer">查看者</option>
                    </select>
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">状态</label>
                    <select
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
                      value={currentUser.status}
                      onChange={(e) => setCurrentUser({ ...currentUser, status: e.target.value as 'active' | 'inactive' | 'locked' })}
                    >
                      <option value="active">活跃</option>
                      <option value="inactive">未激活</option>
                      <option value="locked">已锁定</option>
                    </select>
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">创建日期</label>
                    <input
                      type="text"
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-100 dark:bg-gray-900 text-gray-500 dark:text-gray-400 cursor-not-allowed"
                      value={currentUser.createdAt}
                      disabled
                    />
                  </div>
                </div>
                
                <div className="mt-6">
                  <label className="block text-sm font-medium mb-3">权限设置</label>
                  <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="edit-canManageGoods"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={currentUser.permissions.canManageGoods}
                        onChange={(e) => setCurrentUser({
                          ...currentUser,
                          permissions: {
                            ...currentUser.permissions,
                            canManageGoods: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="edit-canManageGoods" className="ml-2 block text-sm">管理货物</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="edit-canManageRobots"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={currentUser.permissions.canManageRobots}
                        onChange={(e) => setCurrentUser({
                          ...currentUser,
                          permissions: {
                            ...currentUser.permissions,
                            canManageRobots: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="edit-canManageRobots" className="ml-2 block text-sm">管理机器人</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="edit-canManageInventory"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={currentUser.permissions.canManageInventory}
                        onChange={(e) => setCurrentUser({
                          ...currentUser,
                          permissions: {
                            ...currentUser.permissions,
                            canManageInventory: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="edit-canManageInventory" className="ml-2 block text-sm">管理库存</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="edit-canManageUsers"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={currentUser.permissions.canManageUsers}
                        onChange={(e) => setCurrentUser({
                          ...currentUser,
                          permissions: {
                            ...currentUser.permissions,
                            canManageUsers: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="edit-canManageUsers" className="ml-2 block text-sm">管理用户</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="edit-canViewAnalytics"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={currentUser.permissions.canViewAnalytics}
                        onChange={(e) => setCurrentUser({
                          ...currentUser,
                          permissions: {
                            ...currentUser.permissions,
                            canViewAnalytics: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="edit-canViewAnalytics" className="ml-2 block text-sm">查看分析</label>
                    </div>
                    
                    <div className="flex items-center">
                      <input
                        type="checkbox"
                        id="edit-canManageSettings"
                        className="w-4 h-4 text-blue-600 dark:text-blue-400 focus:ring-blue-500 border-gray-300 dark:border-gray-700 rounded"
                        checked={currentUser.permissions.canManageSettings}
                        onChange={(e) => setCurrentUser({
                          ...currentUser,
                          permissions: {
                            ...currentUser.permissions,
                            canManageSettings: e.target.checked
                          }
                        })}
                      />
                      <label htmlFor="edit-canManageSettings" className="ml-2 block text-sm">管理设置</label>
                    </div>
                  </div>
                </div>
              </div>
              
              <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
                <button
                  onClick={() => setIsEditModalOpen(false)}
                  className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                >
                  取消
                </button>
                <button
                  onClick={handleEditUser}
                  className="px-4 py-2 bg-blue-600 dark:bg-blue-700 text-white rounded-lg shadow-sm hover:bg-blue-700 dark:hover:bg-blue-800 transition-colors duration-200"
                >
                  保存
                </button>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
      
      {/* 用户详情模态框 */}
      <AnimatePresence>
        {isDetailModalOpen && currentUser && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
            onClick={() => setIsDetailModalOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.9, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.9, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="bg-white dark:bg-gray-800 rounded-xl shadow-lg w-full max-w-xl max-h-[90vh] overflow-y-auto"
              onClick={(e) => e.stopPropagation()}
            >
              <div className="p-5 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
                <h3 className="font-bold text-lg">用户详情</h3>
                <button onClick={() => setIsDetailModalOpen(false)} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
                  <X size={20} />
                </button>
              </div>
              
              <div className="p-5">
                <div className="mb-6">
                  <div className="flex justify-center mb-4">
                    <div className="w-20 h-20 rounded-full bg-blue-100 dark:bg-blue-900 flex items-center justify-center text-blue-600 dark:text-blue-400">
                      <Users size={32} />
                    </div>
                  </div>
                  <h4 className="text-xl font-bold text-center">{currentUser.realName}</h4>
                  <p className="text-center text-gray-500 dark:text-gray-400">{currentUser.username}</p>
                </div>
                
                <div className="space-y-4">
                  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                      <p className="text-sm text-gray-500 dark:text-gray-400">用户ID</p>
                      <p className="font-medium">{currentUser.id}</p>
                    </div>
                    
                    <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                      <p className="text-sm text-gray-500 dark:text-gray-400">邮箱</p>
                      <p className="font-medium">{currentUser.email}</p>
                    </div>
                    
                    <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                      <p className="text-sm text-gray-500 dark:text-gray-400">电话</p>
                      <p className="font-medium">{currentUser.phone || '-'}</p>
                    </div>
                    
                    <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                      <p className="text-sm text-gray-500 dark:text-gray-400">角色</p>
                      <p className="font-medium">{renderRoleBadge(currentUser.role)}</p>
                    </div>
                    
                    <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                      <p className="text-sm text-gray-500 dark:text-gray-400">状态</p>
                      <p className="font-medium">{renderStatusBadge(currentUser.status)}</p>
                    </div>
                    
                    <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
                      <p className="text-sm text-gray-500 dark:text-gray-400">创建日期</p>
                      <p className="font-medium">{currentUser.createdAt}</p>
                    </div>
                    
                    <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg md:col-span-2">
                      <p className="text-sm text-gray-500 dark:text-gray-400">最后登录</p>
                      <p className="font-medium">{currentUser.lastLogin}</p>
                    </div>
                  </div>
                  
                  <div className="mt-6">
                    <h4 className="font-medium mb-3">权限信息</h4>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                      <div className="flex justify-between items-center p-3 bg-gray-50 dark:bg-gray-900 rounded-lg">
                        <span className="text-sm">管理货物</span>
                        {renderPermissionStatus(currentUser.permissions.canManageGoods)}
                      </div>
                      
                      <div className="flex justify-between items-center p-3 bg-gray-50 dark:bg-gray-900 rounded-lg">
                        <span className="text-sm">管理机器人</span>
                        {renderPermissionStatus(currentUser.permissions.canManageRobots)}
                      </div>
                      
                      <div className="flex justify-between items-center p-3 bg-gray-50 dark:bg-gray-900 rounded-lg">
                        <span className="text-sm">管理库存</span>
                        {renderPermissionStatus(currentUser.permissions.canManageInventory)}
                      </div>
                      
                      <div className="flex justify-between items-center p-3 bg-gray-50 dark:bg-gray-900 rounded-lg">
                        <span className="text-sm">管理用户</span>
                        {renderPermissionStatus(currentUser.permissions.canManageUsers)}
                      </div>
                      
                      <div className="flex justify-between items-center p-3 bg-gray-50 dark:bg-gray-900 rounded-lg">
                        <span className="text-sm">查看分析</span>
                        {renderPermissionStatus(currentUser.permissions.canViewAnalytics)}
                      </div>
                      
                      <div className="flex justify-between items-center p-3 bg-gray-50 dark:bg-gray-900 rounded-lg">
                        <span className="text-sm">管理设置</span>
                        {renderPermissionStatus(currentUser.permissions.canManageSettings)}
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              
              <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
                {currentUser.status === 'active' && (
                  <button
                    onClick={() => {
                      handleStatusChange(currentUser.id, 'locked');
                      setIsDetailModalOpen(false);
                    }}
                    className="px-4 py-2 border border-red-300 dark:border-red-700 rounded-lg bg-white dark:bg-gray-800 text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 transition-colors duration-200"
                  >
                    <Lock size={16} className="inline-block mr-2" /> 锁定用户
                  </button>
                )}
                
                {currentUser.status === 'locked' && (
                  <button
                    onClick={() => {
                      handleStatusChange(currentUser.id, 'active');
                      setIsDetailModalOpen(false);
                    }}
                    className="px-4 py-2 border border-green-300 dark:border-green-700 rounded-lg bg-white dark:bg-gray-800 text-green-600 dark:text-green-400 hover:bg-green-50 dark:hover:bg-green-900/30 transition-colors duration-200"
                  >
                    <Unlock size={16} className="inline-block mr-2" /> 解锁用户
                  </button>
                )}
                
                <button
                  onClick={() => setIsDetailModalOpen(false)}
                  className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                >
                  关闭
                </button>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
      
      {/* 删除确认模态框 */}
      <AnimatePresence>
        {isDeleteModalOpen && currentUser && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
            onClick={() => setIsDeleteModalOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.9, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.9, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="bg-white dark:bg-gray-800 rounded-xl shadow-lg w-full max-w-md"
              onClick={(e) => e.stopPropagation()}
            >
              <div className="p-5 text-center">
                <div className="flex justify-center mb-4">
                  <div className="w-16 h-16 rounded-full bg-red-100 dark:bg-red-900 flex items-center justify-center text-red-600 dark:text-red-400">
                    <AlertCircle size={24} />
                  </div>
                </div>
                <h3 className="font-bold text-lg mb-2">确认删除</h3>
                <p className="text-gray-500 dark:text-gray-400">
                  您确定要删除用户 <span className="font-medium">{currentUser.realName} ({currentUser.username})</span> 吗?此操作无法撤销。
                </p>
              </div>
              
              <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-center space-x-3">
                <button
                  onClick={() => setIsDeleteModalOpen(false)}
                  className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                >
                  取消
                </button>
                <button
                  onClick={handleDeleteUser}
                  className="px-4 py-2 bg-red-600 dark:bg-red-700 text-white rounded-lg shadow-sm hover:bg-red-700 dark:hover:bg-red-800 transition-colors duration-200"
                >
                  删除
                </button>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};



export default UserManagement;
SystemSettings.tsx #系统设置:
bash 复制代码
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { 
  Settings, Save, RefreshCw, Database, Server, Bell, 
  User, Lock, Palette, Info, HelpCircle, LogOut, 
  ChevronDown, ToggleLeft, ToggleRight, FileText, 
  Activity, AlertTriangle, Eye, X
} from 'lucide-react';
import { useTheme } from '@/hooks/useTheme';
import { toast } from 'sonner';

// 系统设置类型定义
interface SystemSettingsType {
  general: {
    siteName: string;
    defaultTheme: 'light' | 'dark' | 'system';
    language: string;
    dateFormat: string;
    timeFormat: string;
  };
  notifications: {
    inventoryAlerts: boolean;
    robotStatusAlerts: boolean;
    systemUpdates: boolean;
    emailNotifications: boolean;
    smsNotifications: boolean;
  };
  security: {
    twoFactorAuth: boolean;
    passwordPolicy: {
      minLength: number;
      requireUppercase: boolean;
      requireLowercase: boolean;
      requireNumbers: boolean;
      requireSpecialChars: boolean;
      passwordExpiryDays: number;
    };
    sessionTimeout: number;
  };
  backup: {
    autoBackup: boolean;
    backupFrequency: 'daily' | 'weekly' | 'monthly';
    backupTime: string;
    backupRetentionDays: number;
    lastBackup: string;
    nextBackup: string;
  };
  warehouse: {
    layout: string;
    zones: number;
    aisles: number;
    rowsPerAisle: number;
    shelvesPerRow: number;
  };
}

// 模拟系统设置数据
const generateMockSettings = (): SystemSettingsType => {
  const now = new Date();
  const lastBackupDate = new Date(now.getTime() - 24 * 60 * 60 * 1000); // 昨天
  const nextBackupDate = new Date(now.getTime() + 24 * 60 * 60 * 1000); // 明天
  
  return {
    general: {
      siteName: '智能无人仓库管理系统',
      defaultTheme: 'system',
      language: '中文',
      dateFormat: 'YYYY-MM-DD',
      timeFormat: '24小时制'
    },
    notifications: {
      inventoryAlerts: true,
      robotStatusAlerts: true,
      systemUpdates: true,
      emailNotifications: true,
      smsNotifications: false
    },
    security: {
      twoFactorAuth: false,
      passwordPolicy: {
        minLength: 8,
        requireUppercase: true,
        requireLowercase: true,
        requireNumbers: true,
        requireSpecialChars: false,
        passwordExpiryDays: 90
      },
      sessionTimeout: 30
    },
    backup: {
      autoBackup: true,
      backupFrequency: 'daily',
      backupTime: '02:00',
      backupRetentionDays: 30,
      lastBackup: lastBackupDate.toLocaleString('zh-CN'),
      nextBackup: nextBackupDate.toLocaleString('zh-CN')
    },
    warehouse: {
      layout: '标准布局',
      zones: 5,
      aisles: 20,
      rowsPerAisle: 8,
      shelvesPerRow: 12
    }
  };
};

const SystemSettings: React.FC = () => {
  const { theme } = useTheme();
  const [settings, setSettings] = useState<SystemSettingsType>(generateMockSettings());
  const [isLoading, setIsLoading] = useState(true);
  const [activeTab, setActiveTab] = useState<'general' | 'notifications' | 'security' | 'backup' | 'warehouse'>('general');
  const [isEditMode, setIsEditMode] = useState(false);
  const [originalSettings, setOriginalSettings] = useState<SystemSettingsType>(generateMockSettings());
  const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false);

  // 加载设置数据
  useEffect(() => {
    // 模拟API请求延迟
    const timer = setTimeout(() => {
      const mockData = generateMockSettings();
      setSettings(mockData);
      setOriginalSettings(mockData);
      setIsLoading(false);
    }, 1000);
    
    return () => clearTimeout(timer);
  }, []);
  
  // 刷新数据
  const handleRefresh = () => {
    setIsLoading(true);
    // 模拟API请求延迟
    const timer = setTimeout(() => {
      const mockData = generateMockSettings();
      setSettings(mockData);
      setOriginalSettings(mockData);
      setIsEditMode(false);
      setIsLoading(false);
      toast.success('设置已刷新');
    }, 1000);
    
    return () => clearTimeout(timer);
  };
  
  // 开始编辑
  const handleStartEdit = () => {
    setIsEditMode(true);
  };
  
  // 取消编辑
  const handleCancelEdit = () => {
    setSettings({ ...originalSettings });
    setIsEditMode(false);
  };
  
  // 保存设置
  const handleSaveSettings = () => {
    setOriginalSettings({ ...settings });
    setIsEditMode(false);
    toast.success('设置已保存');
    
    // 更新备份日期信息
    if (activeTab === 'backup') {
      const now = new Date();
      const nextBackupDate = new Date(now.getTime() + 24 * 60 * 60 * 1000); // 明天
      setSettings(prev => ({
        ...prev,
        backup: {
          ...prev.backup,
          nextBackup: nextBackupDate.toLocaleString('zh-CN')
        }
      }));
    }
  };
  
  // 重置所有设置
  const handleResetSettings = () => {
    setIsConfirmModalOpen(true);
  };
  
  // 确认重置设置
  const confirmResetSettings = () => {
    const defaultSettings = generateMockSettings();
    setSettings(defaultSettings);
    setOriginalSettings(defaultSettings);
    setIsEditMode(false);
    setIsConfirmModalOpen(false);
    toast.success('所有设置已重置为默认值');
  };
  
  // 切换开关状态
  const toggleSetting = (path: string) => {
    setSettings(prev => {
      const newSettings = { ...prev };
      // 简单路径解析,实际项目中可能需要更复杂的处理
      const parts = path.split('.');
      if (parts.length === 2) {
        newSettings[parts[0]][parts[1]] = !newSettings[parts[0]][parts[1]];
      } else if (parts.length === 3) {
        newSettings[parts[0]][parts[1]][parts[2]] = !newSettings[parts[0]][parts[1]][parts[2]];
      }
      return newSettings;
    });
  };
  
  // 更新数值设置
  const updateNumberSetting = (path: string, value: number) => {
    setSettings(prev => {
      const newSettings = { ...prev };
      const parts = path.split('.');
      if (parts.length === 2) {
        newSettings[parts[0]][parts[1]] = value;
      } else if (parts.length === 3) {
        newSettings[parts[0]][parts[1]][parts[2]] = value;
      }
      return newSettings;
    });
  };
  
  // 更新文本设置
  const updateTextSetting = (path: string, value: string) => {
    setSettings(prev => {
      const newSettings = { ...prev };
      const parts = path.split('.');
      if (parts.length === 2) {
        newSettings[parts[0]][parts[1]] = value;
      } else if (parts.length === 3) {
        newSettings[parts[0]][parts[1]][parts[2]] = value;
      }
      return newSettings;
    });
  };

  return (
    <div className="p-4 md:p-6">
      {/* 页面标题和操作区 */}
      <div className="flex flex-col md:flex-row justify-between items-start md:items-center mb-6">
        <div>
          <h2 className="text-2xl font-bold">系统设置</h2>
          <p className="text-gray-500 dark:text-gray-400">配置系统的各项参数和选项</p>
        </div>
        <div className="flex space-x-3 mt-4 md:mt-0">
          <button 
            onClick={handleRefresh}
            className="flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
          >
            <RefreshCw size={16} className="mr-2" />
            刷新
          </button>
          {!isEditMode ? (
            <button 
              onClick={handleStartEdit}
              className="flex items-center px-4 py-2 bg-blue-600 dark:bg-blue-700 text-white rounded-lg shadow-sm hover:bg-blue-700 dark:hover:bg-blue-800 transition-colors duration-200"
            >
              <Settings size={16} className="mr-2" />
              编辑设置
            </button>
          ) : (
            <>
              <button 
                onClick={handleCancelEdit}
                className="flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
              >
                <X size={16} className="mr-2" />
                取消
              </button>
              <button 
                onClick={handleSaveSettings}
                className="flex items-center px-4 py-2 bg-green-600 dark:bg-green-700 text-white rounded-lg shadow-sm hover:bg-green-700 dark:hover:bg-green-800 transition-colors duration-200"
              >
                <Save size={16} className="mr-2" />
                保存设置
              </button>
            </>
          )}
        </div>
      </div>
      
      {/* 标签切换 */}
      <div className="flex border-b border-gray-200 dark:border-gray-700 mb-6 overflow-x-auto">
        <button
          onClick={() => setActiveTab('general')}
          className={`px-4 py-3 font-medium text-sm border-b-2 whitespace-nowrap ${
            activeTab === 'general' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          <Settings size={16} className="inline-block mr-2" />
          基本设置
        </button>
        <button
          onClick={() => setActiveTab('notifications')}
          className={`px-4 py-3 font-medium text-sm border-b-2 whitespace-nowrap ${
            activeTab === 'notifications' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          <Bell size={16} className="inline-block mr-2" />
          通知设置
        </button>
        <button
          onClick={() => setActiveTab('security')}
          className={`px-4 py-3 font-medium text-sm border-b-2 whitespace-nowrap ${
            activeTab === 'security' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          <Lock size={16} className="inline-block mr-2" />
          安全设置
        </button>
        <button
          onClick={() => setActiveTab('backup')}
          className={`px-4 py-3 font-medium text-sm border-b-2 whitespace-nowrap ${
            activeTab === 'backup' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          <Database size={16} className="inline-block mr-2" />
          备份设置
        </button>
        <button
          onClick={() => setActiveTab('warehouse')}
          className={`px-4 py-3 font-medium text-sm border-b-2 whitespace-nowrap ${
            activeTab === 'warehouse' 
              ? 'border-blue-500 text-blue-600 dark:text-blue-400' 
              : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
          }`}
        >
          <Server size={16} className="inline-block mr-2" />
          仓库设置
        </button>
      </div>
      
      {/* 主要内容区域 */}
      <div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-5 mb-6">
        {isLoading ? (
          <div className="h-96 flex items-center justify-center">
            <div className="flex flex-col items-center">
              <RefreshCw size={32} className="text-blue-500 animate-spin" />
              <p className="mt-2 text-gray-500 dark:text-gray-400">加载设置中...</p>
            </div>
          </div>
        ) : (
          <>
            {/* 基本设置 */}
            {activeTab === 'general' && (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ duration: 0.5 }}
              >
                <h3 className="text-lg font-medium mb-4">基本设置</h3>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                  <div>
                    <label className="block text-sm font-medium mb-2">系统名称</label>
                    <input
                      type="text"
                      className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                      value={settings.general.siteName}
                      onChange={(e) => updateTextSetting('general.siteName', e.target.value)}
                      disabled={!isEditMode}
                    />
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">默认主题</label>
                    <select
                      className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                      value={settings.general.defaultTheme}
                      onChange={(e) => updateTextSetting('general.defaultTheme', e.target.value)}
                      disabled={!isEditMode}
                    >
                      <option value="light">浅色模式</option>
                      <option value="dark">深色模式</option>
                      <option value="system">跟随系统</option>
                    </select>
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">语言</label>
                    <select className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                      value={settings.general.language}
                      onChange={(e) => updateTextSetting('general.language', e.target.value)}
                      disabled={!isEditMode}
                    >
                      <option value="中文">中文</option>
                      <option value="English">English</option>
                    </select>
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">日期格式</label>
                    <select
                      className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                      value={settings.general.dateFormat}
                      onChange={(e) => updateTextSetting('general.dateFormat', e.target.value)}
                      disabled={!isEditMode}
                    >
                      <option value="YYYY-MM-DD">YYYY-MM-DD</option>
                      <option value="DD/MM/YYYY">DD/MM/YYYY</option>
                      <option value="MM/DD/YYYY">MM/DD/YYYY</option>
                    </select>
                  </div>
                  
                  <div>
                    <label className="block text-sm font-medium mb-2">时间格式</label>
                    <select
                      className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                      value={settings.general.timeFormat}
                      onChange={(e) => updateTextSetting('general.timeFormat', e.target.value)}
                      disabled={!isEditMode}
                    >
                      <option value="24小时制">24小时制</option>
                      <option value="12小时制">12小时制</option>
                    </select>
                  </div>
                </div>
                
                <div className="mt-6 p-4 bg-blue-50 dark:bg-blue-900/30 rounded-lg border border-blue-100 dark:border-blue-800">
                  <div className="flex">
                    <Info size={20} className="text-blue-600 dark:text-blue-400 mr-3 flex-shrink-0 mt-0.5" />
                    <p className="text-sm text-blue-700 dark:text-blue-300">
                      基本设置将影响整个系统的外观和行为。更改系统名称、默认主题和语言等设置后,所有用户都会受到影响。
                    </p>
                  </div>
                </div>
              </motion.div>
            )}
            
            {/* 通知设置 */}
            {activeTab === 'notifications' && (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ duration: 0.5 }}
              >
                <h3 className="text-lg font-medium mb-4">通知设置</h3>
                <div className="space-y-4">
                  <div className="flex items-center justify-between p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <div>
                      <h4 className="font-medium">库存警报</h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">当库存水平达到预警阈值时发送通知</p>
                    </div>
                    <button
                      onClick={() => toggleSetting('notifications.inventoryAlerts')}
                      disabled={!isEditMode}
                      className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                    >
                      {settings.notifications.inventoryAlerts ? (
                        <ToggleRight size={24} className="text-green-500" />
                      ) : (
                        <ToggleLeft size={24} className="text-gray-400" />
                      )}
                    </button>
                  </div>
                  
                  <div className="flex items-center justify-between p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <div>
                      <h4 className="font-medium">机器人状态警报</h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">当机器人出现故障或需要维护时发送通知</p>
                    </div>
                    <button
                      onClick={() => toggleSetting('notifications.robotStatusAlerts')}
                      disabled={!isEditMode}
                      className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                    >
                      {settings.notifications.robotStatusAlerts ? (
                        <ToggleRight size={24} className="text-green-500" />
                      ) : (
                        <ToggleLeft size={24} className="text-gray-400" />
                      )}
                    </button>
                  </div>
                  
                  <div className="flex items-center justify-between p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <div>
                      <h4 className="font-medium">系统更新通知</h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">当系统有新的更新可用时发送通知</p>
                    </div>
                    <button
                      onClick={() => toggleSetting('notifications.systemUpdates')}
                      disabled={!isEditMode}
                      className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                    >
                      {settings.notifications.systemUpdates ? (
                        <ToggleRight size={24} className="text-green-500" />
                      ) : (
                        <ToggleLeft size={24} className="text-gray-400" />
                      )}
                    </button>
                  </div>
                  
                  <div className="flex items-center justify-between p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <div>
                      <h4 className="font-medium">电子邮件通知</h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">通过电子邮件发送通知</p>
                    </div>
                    <button
                      onClick={() => toggleSetting('notifications.emailNotifications')}
                      disabled={!isEditMode}
                      className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                    >
                      {settings.notifications.emailNotifications ? (
                        <ToggleRight size={24} className="text-green-500" />
                      ) : (
                        <ToggleLeft size={24} className="text-gray-400" />
                      )}
                    </button>
                  </div>
                  
                  <div className="flex items-center justify-between p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <div>
                      <h4 className="font-medium">短信通知</h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">通过短信发送重要通知</p>
                    </div>
                    <button
                      onClick={() => toggleSetting('notifications.smsNotifications')}
                      disabled={!isEditMode}
                      className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                    >
                      {settings.notifications.smsNotifications ? (
                        <ToggleRight size={24} className="text-green-500" />
                      ) : (
                        <ToggleLeft size={24} className="text-gray-400" />
                      )}
                    </button>
                  </div>
                </div>
                
                <div className="mt-6 p-4 bg-yellow-50 dark:bg-yellow-900/30 rounded-lg border border-yellow-100 dark:border-yellow-800">
                  <div className="flex">
                    <AlertTriangle size={20} className="text-yellow-600 dark:text-yellow-400 mr-3 flex-shrink-0 mt-0.5" />
                    <p className="text-sm text-yellow-700 dark:text-yellow-300">
                      请注意,短信通知可能产生额外费用。建议仅为重要警报启用短信通知。
                    </p>
                  </div>
                </div>
              </motion.div>
            )}
            
            {/* 安全设置 */}
            {activeTab === 'security' && (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ duration: 0.5 }}
              >
                <h3 className="text-lg font-medium mb-4">安全设置</h3>
                <div className="space-y-4">
                  <div className="flex items-center justify-between p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <div>
                      <h4 className="font-medium">两步验证</h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">登录时需要额外的验证步骤</p>
                    </div>
                    <button
                      onClick={() => toggleSetting('security.twoFactorAuth')}
                      disabled={!isEditMode}
                      className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                    >
                      {settings.security.twoFactorAuth ? (
                        <ToggleRight size={24} className="text-green-500" />
                      ) : (
                        <ToggleLeft size={24} className="text-gray-400" />
                      )}
                    </button>
                  </div>
                  
                  <div className="p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <h4 className="font-medium mb-3">密码策略</h4>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                      <div>
                        <label className="block text-sm font-medium mb-2">最小长度</label>
                        <input
                          type="number"
                          min="6"
                          max="32"
                          className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                          value={settings.security.passwordPolicy.minLength}
                          onChange={(e) => updateNumberSetting('security.passwordPolicy.minLength', parseInt(e.target.value) || 8)}
                          disabled={!isEditMode}
                        />
                      </div>
                      
                      <div>
                        <label className="block text-sm font-medium mb-2">密码过期天数</label>
                        <input
                          type="number"
                          min="0"
                          max="365"
                          className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                          value={settings.security.passwordPolicy.passwordExpiryDays}
                          onChange={(e) => updateNumberSetting('security.passwordPolicy.passwordExpiryDays', parseInt(e.target.value) || 90)}
                          disabled={!isEditMode}
                        />
                      </div>
                      
                      <div className="flex items-center justify-between">
                        <label className="block text-sm font-medium">需要大写字母</label>
                        <button
                          onClick={() => toggleSetting('security.passwordPolicy.requireUppercase')}
                          disabled={!isEditMode}
                          className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                        >
                          {settings.security.passwordPolicy.requireUppercase ? (
                            <ToggleRight size={24} className="text-green-500" />
                          ) : (
                            <ToggleLeft size={24} className="text-gray-400" />
                          )}
                        </button>
                      </div>
                      
                      <div className="flex items-center justify-between">
                        <label className="block text-sm font-medium">需要小写字母</label>
                        <button
                          onClick={() => toggleSetting('security.passwordPolicy.requireLowercase')}
                          disabled={!isEditMode}
                          className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                        >
                          {settings.security.passwordPolicy.requireLowercase ? (
                            <ToggleRight size={24} className="text-green-500" />
                          ) : (
                            <ToggleLeft size={24} className="text-gray-400" />
                          )}
                        </button>
                      </div>
                      
                      <div className="flex items-center justify-between">
                        <label className="block text-sm font-medium">需要数字</label>
                        <button
                          onClick={() => toggleSetting('security.passwordPolicy.requireNumbers')}
                          disabled={!isEditMode}
                          className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                        >
                          {settings.security.passwordPolicy.requireNumbers ? (
                            <ToggleRight size={24} className="text-green-500" />
                          ) : (
                            <ToggleLeft size={24} className="text-gray-400" />
                          )}
                        </button>
                      </div>
                      
                      <div className="flex items-center justify-between">
                        <label className="block text-sm font-medium">需要特殊字符</label>
                        <button
                          onClick={() => toggleSetting('security.passwordPolicy.requireSpecialChars')}
                          disabled={!isEditMode}
                          className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                        >
                          {settings.security.passwordPolicy.requireSpecialChars ? (
                            <ToggleRight size={24} className="text-green-500" />
                          ) : (
                            <ToggleLeft size={24} className="text-gray-400" />
                          )}
                        </button>
                      </div>
                    </div>
                  </div>
                  
                  <div className="p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <h4 className="font-medium mb-3">会话设置</h4>
                    <div>
                      <label className="block text-sm font-medium mb-2">会话超时时间(分钟)</label>
                      <input
                        type="number"
                        min="5"
                        max="120"
                        className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                        value={settings.security.sessionTimeout}
                        onChange={(e) => updateNumberSetting('security.sessionTimeout', parseInt(e.target.value) || 30)}
                        disabled={!isEditMode}
                      />
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">用户在指定时间内无操作将自动登出</p>
                    </div>
                  </div>
                </div>
                
                <div className="mt-6 p-4 bg-red-50 dark:bg-red-900/30 rounded-lg border border-red-100 dark:border-red-800">
                  <div className="flex">
                    <Lock size={20} className="text-red-600 dark:text-red-400 mr-3 flex-shrink-0 mt-0.5" />
                    <p className="text-sm text-red-700 dark:text-red-300">
                      安全设置对系统安全性至关重要。建议启用两步验证并设置强密码策略以保护系统免受未授权访问。
                    </p>
                  </div>
                </div>
              </motion.div>
            )}
            
            {/* 备份设置 */}
            {activeTab === 'backup' && (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ duration: 0.5 }}
              >
                <h3 className="text-lg font-medium mb-4">备份设置</h3>
                <div className="space-y-4">
                  <div className="flex items-center justify-between p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <div>
                      <h4 className="font-medium">自动备份</h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">定期自动备份系统数据</p>
                    </div>
                    <button
                      onClick={() => toggleSetting('backup.autoBackup')}
                      disabled={!isEditMode}
                      className={`p-1 rounded-full ${isEditMode ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'}`}
                    >
                      {settings.backup.autoBackup ? (
                        <ToggleRight size={24} className="text-green-500" />
                      ) : (
                        <ToggleLeft size={24} className="text-gray-400" />
                      )}
                    </button>
                  </div>
                  
                  <div className="p-4 border border-gray-200 dark:border-gray-700 rounded-lg">
                    <h4 className="font-medium mb-3">备份计划</h4>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                      <div>
                        <label className="block text-sm font-medium mb-2">备份频率</label>
                        <select
                          className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                          value={settings.backup.backupFrequency}
                          onChange={(e) => updateTextSetting('backup.backupFrequency', e.target.value)}
                          disabled={!isEditMode}
                        >
                          <option value="daily">每日</option>
                          <option value="weekly">每周</option>
                          <option value="monthly">每月</option>
                        </select>
                      </div>
                      
                      <div>
                        <label className="block text-sm font-medium mb-2">备份时间</label>
                        <input
                          type="time"
                          className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                          value={settings.backup.backupTime}
                          onChange={(e) => updateTextSetting('backup.backupTime', e.target.value)}
                          disabled={!isEditMode}
                        />
                      </div>
                      
                      <div>
                        <label className="block text-sm font-medium mb-2">备份保留天数</label>
                        <input
                          type="number"
                          min="1"
                          max="365"
                          className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                          value={settings.backup.backupRetentionDays}
                          onChange={(e) => updateNumberSetting('backup.backupRetentionDays', parseInt(e.target.value) || 30)}
                          disabled={!isEditMode}
                        />
                      </div>
                    </div>
                  </div>
                  
                  <div className="p-4 border border-gray-200 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800/50">
                    <h4 className="font-medium mb-3">备份状态</h4>
                    <div className="space-y-3">
                      <div>
                        <label className="block text-sm font-medium text-gray-500 dark:text-gray-400">上次备份</label>
                        <p className="text-sm mt-1">{settings.backup.lastBackup}</p>
                      </div>
                      <div>
                        <label className="block text-sm font-medium text-gray-500 dark:text-gray-400">下次备份</label>
                        <p className="text-sm mt-1">{settings.backup.nextBackup}</p>
                      </div>
                    </div>
                  </div>
                </div>
                
                <div className="mt-6 p-4 bg-green-50 dark:bg-green-900/30 rounded-lg border border-green-100 dark:border-green-800">
                  <div className="flex">
                    <Database size={20} className="text-green-600 dark:text-green-400 mr-3 flex-shrink-0 mt-0.5" />
                    <p className="text-sm text-green-700 dark:text-green-300">
                      定期备份是数据安全的重要保障。建议设置合理的备份频率和保留时间,确保数据可以在意外情况下恢复。
                    </p>
                  </div>
                </div>
              </motion.div>
            )}
            
            {/* 仓库设置 */}
            {activeTab === 'warehouse' && (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ duration: 0.5 }}
              >
                <h3 className="text-lg font-medium mb-4">仓库设置</h3>
                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-medium mb-2">仓库布局</label>
                    <select
                      className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                      value={settings.warehouse.layout}
                      onChange={(e) => updateTextSetting('warehouse.layout', e.target.value)}
                      disabled={!isEditMode}
                    >
                      <option value="标准布局">标准布局</option>
                      <option value="优化布局">优化布局</option>
                      <option value="自定义布局">自定义布局</option>
                    </select>
                  </div>
                  
                  <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4">
                    <div>
                      <label className="block text-sm font-medium mb-2">区域数量</label>
                      <input
                        type="number"
                        min="1"
                        max="20"
                        className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                        value={settings.warehouse.zones}
                        onChange={(e) => updateNumberSetting('warehouse.zones', parseInt(e.target.value) || 5)}
                        disabled={!isEditMode}
                      />
                    </div>
                    
                    <div>
                      <label className="block text-sm font-medium mb-2">通道数量</label>
                      <input
                        type="number"
                        min="1"
                        max="50"
                        className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                        value={settings.warehouse.aisles}
                        onChange={(e) => updateNumberSetting('warehouse.aisles', parseInt(e.target.value) || 20)}
                        disabled={!isEditMode}
                      />
                    </div>
                    
                    <div>
                      <label className="block text-sm font-medium mb-2">每通道行数</label>
                      <input
                        type="number"
                        min="1"
                        max="20"
                        className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                        value={settings.warehouse.rowsPerAisle}
                        onChange={(e) => updateNumberSetting('warehouse.rowsPerAisle', parseInt(e.target.value) || 8)}
                        disabled={!isEditMode}
                      />
                    </div>
                    
                    <div>
                      <label className="block text-sm font-medium mb-2">每行货架数</label>
                      <input
                        type="number"
                        min="1"
                        max="30"
                        className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isEditMode ? '' : 'cursor-not-allowed'}`}
                        value={settings.warehouse.shelvesPerRow}
                        onChange={(e) => updateNumberSetting('warehouse.shelvesPerRow', parseInt(e.target.value) || 12)}
                        disabled={!isEditMode}
                      />
                    </div>
                  </div>
                  
                  <div className="p-4 border border-gray-200 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800/50">
                    <h4 className="font-medium mb-3">仓库容量计算</h4>
                    <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                      <div>
                        <label className="block text-sm font-medium text-gray-500 dark:text-gray-400">总货架数量</label>
                        <p className="text-sm font-medium mt-1">
                          {settings.warehouse.zones * settings.warehouse.aisles * settings.warehouse.rowsPerAisle * settings.warehouse.shelvesPerRow}
                        </p>
                      </div>
                      <div>
                        <label className="block text-sm font-medium text-gray-500 dark:text-gray-400">估算容量</label>
                        <p className="text-sm font-medium mt-1">
                          {settings.warehouse.zones * settings.warehouse.aisles * settings.warehouse.rowsPerAisle * settings.warehouse.shelvesPerRow * 50} 个货物单元
                        </p>
                      </div>
                    </div>
                  </div>
                </div>
                
                <div className="mt-6 p-4 bg-orange-50 dark:bg-orange-900/30 rounded-lg border border-orange-100 dark:border-orange-800">
                  <div className="flex">
                    <Activity size={20} className="text-orange-600 dark:text-orange-400 mr-3 flex-shrink-0 mt-0.5" />
                    <p className="text-sm text-orange-700 dark:text-orange-300">
                      仓库设置会影响机器人路径规划和货物存放策略。更改这些设置后,建议重新校准机器人系统以获得最佳性能。
                    </p>
                  </div>
                </div>
              </motion.div>
            )}
            
            {/* 底部操作按钮 */}
            <div className="mt-6 pt-4 border-t border-gray-200 dark:border-gray-700 flex justify-end">
              <button
                onClick={handleResetSettings}
                className="px-4 py-2 border border-red-300 dark:border-red-700 rounded-lg bg-white dark:bg-gray-800 text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 transition-colors duration-200"
              >
                重置为默认设置
              </button>
            </div>
          </>
        )}
      </div>
      
      {/* 系统信息卡片 */}
      <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-4"
        >
          <div className="flex items-center mb-2">
            <Info size={18} className="mr-2 text-blue-500" />
            <h3 className="font-medium">系统版本</h3>
          </div>
          <p className="text-sm">v1.2.0</p>
          <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">最后更新: 2025-09-15</p>
        </motion.div>
        
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3, delay: 0.1 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-4"
        >
          <div className="flex items-center mb-2">
            <FileText size={18} className="mr-2 text-green-500" />
            <h3 className="font-medium">文档</h3>
          </div>
          <a href="#" className="text-sm text-blue-600 dark:text-blue-400 hover:underline">用户手册</a>
          <br />
          <a href="#" className="text-sm text-blue-600 dark:text-blue-400 hover:underline mt-1">API文档</a>
        </motion.div>
        
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3, delay: 0.2 }}
          className="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-4"
        >
          <div className="flex items-center mb-2">
            <HelpCircle size={18} className="mr-2 text-purple-500" />
            <h3 className="font-medium">支持</h3>
          </div>
          <p className="text-sm">support@example.com</p>
          <p className="text-sm mt-1">+86 400-123-4567</p>
        </motion.div>
      </div>
      
      {/* 确认重置模态框 */}
      <AnimatePresence>
        {isConfirmModalOpen && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
            onClick={() => setIsConfirmModalOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.9, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.9, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="bg-white dark:bg-gray-800 rounded-xl shadow-lg w-full max-w-md"
              onClick={(e) => e.stopPropagation()}
            >
              <div className="p-5 text-center">
                <div className="flex justify-center mb-4">
                  <div className="w-16 h-16 rounded-full bg-red-100 dark:bg-red-900 flex items-center justify-center text-red-600 dark:text-red-400">
                    <AlertTriangle size={24} />
                  </div>
                </div>
                <h3 className="font-bold text-lg mb-2">确认重置</h3>
                <p className="text-gray-500 dark:text-gray-400">
                  您确定要将所有系统设置重置为默认值吗?此操作无法撤销,会影响所有用户的使用体验。
                </p>
              </div>
              
              <div className="p-5 border-t border-gray-200 dark:border-gray-700 flex justify-center space-x-3">
                <button
                  onClick={() => setIsConfirmModalOpen(false)}
                  className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
                >
                  取消
                </button>
                <button
                  onClick={confirmResetSettings}
                  className="px-4 py-2 bg-red-600 dark:bg-red-700 text-white rounded-lg shadow-sm hover:bg-red-700 dark:hover:bg-red-800 transition-colors duration-200"
                >
                  确认重置
                </button>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

export default SystemSettings;
相关推荐
打小就很皮...4 小时前
PDF 下载弹窗 content 区域可行性方案
前端·javascript·pdf
Felicity_Gao7 小时前
uni-app VOD 与 COS 选型、开发笔记
前端·笔记·uni-app
我狸才不是赔钱货8 小时前
前端技术栈全景图:从HTML到现代框架的演进之路
前端·html
百花~9 小时前
前端三剑客之一 HTML~
前端·html
lang201509289 小时前
Spring远程调用与Web服务全解析
java·前端·spring
listhi52011 小时前
利用React Hooks简化状态管理
前端·javascript·react.js
一点一木12 小时前
🚀 2025 年 10 月 GitHub 十大热门项目排行榜 🔥
前端·人工智能·github
华仔啊12 小时前
这个Vue3旋转菜单组件让项目颜值提升200%!支持多种主题,拿来即用
前端·javascript·css
非凡ghost12 小时前
Adobe Lightroom安卓版(手机调色软件)绿色版
前端·windows·adobe·智能手机·软件需求