import React, { useState, useEffect, useMemo } from 'react'; import { Layout, Menu, Typography, Avatar, Dropdown, Badge, Space, Tag, Divider, Switch, message, Button } from 'antd'; import { DashboardOutlined, ShoppingOutlined, FileTextOutlined, UserOutlined, TruckOutlined, AlertOutlined, SettingOutlined, MenuFoldOutlined, MenuUnfoldOutlined, BellOutlined, DownOutlined, ShopOutlined, WalletOutlined, GlobalOutlined, RobotOutlined, AppstoreOutlined, LineChartOutlined, SafetyOutlined, CrownOutlined, SwapOutlined, ClusterOutlined, } from '@ant-design/icons'; import { Link, useLocation, useNavigate, Outlet } from 'react-router-dom'; import type { MenuProps } from 'antd'; import { UserProvider, useUser, MOCK_USERS, ROLE_CONFIG, FEATURES, PERMISSIONS, UserRole } from '@/contexts/UserContext'; import { useLocale } from '@/contexts/LocaleContext'; const { Header, Sider, Content } = Layout; const { Title, Text } = Typography; interface CustomMenuItem { key: string; icon?: React.ReactNode; label?: React.ReactNode; requiredPermission?: string | null; requiredFeature?: string | null; children?: CustomMenuItem[]; type?: 'divider' | 'group'; } type MenuItem = Required['items'][number]; const ALL_MENU_ITEMS: CustomMenuItem[] = [ { key: '/dashboard', icon: , label: 数据概览, requiredPermission: null, }, { key: 'ai-operations', icon: , label: 'AI运营中心', requiredFeature: FEATURES.AI_OPERATIONS, children: [ { key: '/dashboard/operation-agent', label: 运营Agent }, { key: '/dashboard/auto-pilot', label: 自动驾驶 }, { key: '/dashboard/task-center', label: 任务中心 }, { key: '/dashboard/ai-decision-log', label: AI决策日志 }, { key: '/dashboard/strategy-marketplace', label: 策略市场 }, { key: '/dashboard/auto-product-selection', label: 自动选品 }, { key: '/dashboard/auto-execution', label: 自动执行 }, ], }, { key: 'product-cycle', icon: , label: '商品闭环', children: [ { key: '/dashboard/product', label: 商品管理, requiredPermission: PERMISSIONS.PRODUCT_READ }, { key: '/dashboard/product/publish', label: 商品发布, requiredPermission: PERMISSIONS.PRODUCT_WRITE }, { key: '/dashboard/inventory', label: 库存管理, requiredPermission: PERMISSIONS.INVENTORY_READ }, { key: '/dashboard/inventory/warehouses', label: 仓库管理 }, { key: '/dashboard/product/ai-pricing', label: AI定价, requiredFeature: FEATURES.AUTO_PRICING }, { key: '/dashboard/product/profit-monitor', label: 利润监控 }, ], }, { key: 'order-cycle', icon: , label: '订单闭环', children: [ { key: '/dashboard/orders', label: 订单管理, requiredPermission: PERMISSIONS.ORDER_READ }, { key: '/dashboard/orders/exception', label: 异常订单 }, { key: '/dashboard/after-sales', label: 售后服务 }, { key: '/dashboard/after-sales/refund', label: 退款处理 }, ], }, { key: 'logistics-cycle', icon: , label: '物流闭环', requiredPermission: PERMISSIONS.INVENTORY_READ, children: [ { key: '/dashboard/logistics', label: 物流查询 }, { key: '/dashboard/logistics/freight-calc', label: 运费计算 }, ], }, { key: 'finance-cycle', icon: , label: '财务闭环', requiredPermission: PERMISSIONS.FINANCE_READ, children: [ { key: '/dashboard/finance', label: 财务概览 }, { key: '/dashboard/finance/transactions', label: 交易记录 }, { key: '/dashboard/finance/reconciliation', label: 财务对账 }, { key: '/dashboard/user-asset', label: 用户资产 }, ], }, { key: 'marketing-cycle', icon: , label: '营销闭环', children: [ { key: '/dashboard/ad', label: 广告管理 }, { key: '/dashboard/marketing/competitors', label: 竞品分析 }, { key: '/dashboard/dynamic-pricing', label: 动态定价, requiredFeature: FEATURES.AUTO_PRICING }, { key: '/dashboard/ab-test', label: AB测试 }, ], }, { key: 'analytics', icon: , label: '数据分析', children: [ { key: '/dashboard/analytics', label: 数据分析 }, { key: '/dashboard/reports', label: 报表中心 }, { key: '/dashboard/multi-shop-report', label: 多店报表, requiredFeature: FEATURES.MULTI_SHOP }, { key: '/dashboard/leaderboard', label: 收益排行 }, ], }, { key: 'b2b-trade', icon: , label: 'B2B贸易', requiredFeature: FEATURES.B2B_TRADE, children: [ { key: '/dashboard/merchant', label: 商户管理 }, { key: '/dashboard/b2b', label: B2B贸易 }, { key: '/dashboard/suppliers', label: 供应商 }, ], }, { key: 'independent-site', icon: , label: '独立站', requiredFeature: FEATURES.INDEPENDENT_SITE, children: [ { key: '/dashboard/independent-site', label: 站点管理 }, { key: '/dashboard/independent-site/domains', label: 域名管理 }, ], }, { key: 'risk-compliance', icon: , label: '风控合规', children: [ { key: '/dashboard/compliance', label: 合规概览 }, { key: '/dashboard/compliance/certificates', label: 证书管理 }, { key: '/dashboard/blacklist', label: 黑名单 }, ], }, { key: 'settings', icon: , label: '系统设置', children: [ { key: '/dashboard/settings', label: 设置概览 }, { key: '/dashboard/settings/platform-auth', label: 平台授权 }, { key: '/dashboard/settings/service-manager', label: 服务管理 }, { key: '/dashboard/user', label: 用户管理 }, { key: '/dashboard/role', label: 角色权限 }, ], }, ]; const MainLayoutContent: React.FC = () => { const [collapsed, setCollapsed] = useState(false); const location = useLocation(); const navigate = useNavigate(); const { currentUser, setCurrentUser, hasPermission, hasFeature, getPlanLabel, isPaidUser } = useUser(); const { locale, setLocale } = useLocale(); const menuItems = useMemo(() => { const stripCustomProps = (item: CustomMenuItem): MenuItem => { const { requiredPermission, requiredFeature, ...rest } = item; return rest as MenuItem; }; const filterMenuItems = (items: CustomMenuItem[]): MenuItem[] => { const result: MenuItem[] = []; items.forEach((item) => { if (item.requiredFeature && !hasFeature(item.requiredFeature)) { return; } if (item.requiredPermission && !hasPermission(item.requiredPermission)) { return; } if (item.children && Array.isArray(item.children)) { const filteredChildren = filterMenuItems(item.children); if (filteredChildren.length > 0) { result.push(stripCustomProps({ ...item, children: filteredChildren as CustomMenuItem[] })); } } else { result.push(stripCustomProps(item)); } }); return result; }; return filterMenuItems(ALL_MENU_ITEMS); }, [hasPermission, hasFeature]); const getSelectedKeys = (): string[] => { const pathname = location.pathname; let bestMatch: string | null = null; let bestMatchLength = 0; const findMatch = (items: MenuItem[]) => { items.forEach((item) => { if (item && 'key' in item && typeof item.key === 'string') { const key = item.key; if (pathname === key || pathname.startsWith(key + '/')) { if (key.length > bestMatchLength) { bestMatch = key; bestMatchLength = key.length; } } } if (item && 'children' in item && Array.isArray(item.children)) { findMatch(item.children); } }); }; findMatch(menuItems); return bestMatch ? [bestMatch] : []; }; const getOpenKeys = (): string[] => { const pathname = location.pathname; const openKeys: string[] = []; const findParent = (items: MenuItem[], parentKey?: string) => { items.forEach((item) => { if (item && 'key' in item && typeof item.key === 'string') { const key = item.key; if (pathname === key || pathname.startsWith(key + '/')) { if (parentKey) { openKeys.push(parentKey); } } } if (item && 'children' in item && Array.isArray(item.children)) { const itemKey = 'key' in item ? item.key as string : undefined; findParent(item.children, itemKey); } }); }; findParent(menuItems); return Array.from(new Set(openKeys)); }; const selectedKeys = getSelectedKeys(); const openKeys = getOpenKeys(); useEffect(() => { const savedCollapsed = localStorage.getItem('sidebar_collapsed'); if (savedCollapsed !== null) { setCollapsed(savedCollapsed === 'true'); } }, []); const handleCollapse = (value: boolean) => { setCollapsed(value); localStorage.setItem('sidebar_collapsed', String(value)); }; const handleUserMenuClick = ({ key }: { key: string }) => { if (key === 'logout') { localStorage.removeItem('token'); navigate('/auth/login'); } else if (key === 'profile') { navigate('/dashboard/settings/profile'); } else if (key === 'settings') { navigate('/dashboard/settings'); } else if (key === 'subscription') { navigate('/dashboard/settings/subscription'); } }; const handleSwitchUser = (userId: string) => { const user = MOCK_USERS.find(u => u.id === userId); if (user) { setCurrentUser(user); message.success(`已切换到 ${user.name} (${ROLE_CONFIG[user.role].label})`); } }; const userMenuItems: MenuItem[] = [ { key: 'profile', icon: , label: '个人中心', }, { key: 'subscription', icon: , label: '订阅管理', }, { key: 'settings', icon: , label: '账号设置', }, { type: 'divider' }, { key: 'logout', icon: , label: '退出登录', }, ]; const planColors: Record = { free: 'default', basic: 'blue', pro: 'gold', enterprise: 'purple', }; return (
{collapsed ? (
C
) : ( Crawlful Hub )}
handleCollapse(!collapsed)} > {collapsed ? ( ) : ( )}
Crawlful Hub 管理后台
({ key: user.id, label: ( {user.name} {ROLE_CONFIG[user.role].label} {getPlanLabel()} ), })), onClick: ({ key }) => handleSwitchUser(key), }} placement="bottomRight" > setLocale(key), selectedKeys: [locale], }} placement="bottomRight" > } />
{currentUser.name} {ROLE_CONFIG[currentUser.role].label} {getPlanLabel()}
); }; const MainLayout: React.FC = () => { return ( ); }; export default MainLayout;