"use client" import { Activity, BarChart3, ChevronsLeft, ChevronsRight, CircleDollarSign, ClipboardList, ComputerIcon, ContactRound, DollarSign, DoorClosedIcon, FolderCode, Home, KeyRound, type LucideIcon, Package, ScanSearch, Shield, ShoppingBag, SquarePercent, TicketPercent, Users, } from "lucide-react" import Link from "next/link" import { usePathname } from "next/navigation" import { createContext, type ReactNode, useContext, useState } from "react" import { twJoin } from "tailwind-merge" import { Auth } from "@/components/auth" import { Button } from "@/components/ui/button" import { ScrollArea } from "@/components/ui/scroll-area" import { Separator } from "@/components/ui/separator" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { ScopeAdminRead, ScopeAdminRoleRead, ScopeBalanceActivity, ScopeBatchRead, ScopeBillRead, ScopeChannelRead, ScopeCouponRead, ScopeDiscountRead, ScopePermissionRead, ScopeProductRead, ScopeProxyRead, ScopeResourceRead, ScopeTradeRead, ScopeUserRead, ScopeUserReadNotBind, ScopeUserReadOne, } from "@/lib/scopes" // Navigation Context interface NavigationContextType { collapsed: boolean pathname: string isActive: (path: string) => boolean } const NavigationContext = createContext( undefined, ) const useNavigation = () => { const context = useContext(NavigationContext) if (!context) { throw new Error("Navigation components must be used within Navigation") } return context } // NavGroup Component interface NavGroupProps { title: string children: ReactNode } function NavGroup({ title, children }: NavGroupProps) { const { collapsed } = useNavigation() return (
{!collapsed && (

{title}

)}
) } // NavItem Component interface NavItemProps { href: string icon: LucideIcon label: string requiredScope?: string } function NavItem({ href, icon: Icon, label, requiredScope }: NavItemProps) { const { collapsed, isActive } = useNavigation() const active = isActive(href) let linkContent = ( {!collapsed && {label}} ) if (collapsed) { linkContent = ( {linkContent}

{label}

) } if (requiredScope) { linkContent = (
  • {linkContent}
  • ) } return linkContent } // NavSeparator Component function NavSeparator() { const { collapsed } = useNavigation() if (collapsed) return null return (
    ) } const menuSections: { title: string; items: NavItemProps[] }[] = [ { title: "概览", items: [ { href: "/", icon: Home, label: "首页" }, { href: "/statistics", icon: BarChart3, label: "数据统计" }, ], }, { title: "客户", items: [ { href: "/user", icon: Users, label: "客户认领", requiredScope: ScopeUserReadNotBind, }, { href: "/client/cust", icon: ScanSearch, label: "客户查询", requiredScope: ScopeUserReadOne, }, { href: "/cust", icon: ContactRound, label: "客户管理", requiredScope: ScopeUserRead, }, { href: "/trade", icon: Activity, label: "交易明细", requiredScope: ScopeTradeRead, }, { href: "/balance", icon: CircleDollarSign, label: "余额明细", requiredScope: ScopeBalanceActivity, }, { href: "/billing", icon: DollarSign, label: "账单详情", requiredScope: ScopeBillRead, }, ], }, { title: "运营", items: [ { href: "/product", icon: ShoppingBag, label: "产品管理", requiredScope: ScopeProductRead, }, { href: "/discount", icon: SquarePercent, label: "折扣管理", requiredScope: ScopeDiscountRead, }, { href: "/coupon", icon: TicketPercent, label: "优惠券", requiredScope: ScopeCouponRead, }, { href: "/resources", icon: Package, label: "套餐管理", requiredScope: ScopeResourceRead, }, { href: "/batch", icon: ClipboardList, label: "提取记录", requiredScope: ScopeBatchRead, }, { href: "/channel", icon: FolderCode, label: "IP管理", requiredScope: ScopeChannelRead, }, ], }, { title: "系统", items: [ { href: "/gateway", icon: DoorClosedIcon, label: "网关列表", requiredScope:ScopeProxyRead }, { href: "/admin", icon: Shield, label: "管理员", requiredScope: ScopeAdminRead, }, { href: "/roles", icon: KeyRound, label: "角色列表", requiredScope: ScopeAdminRoleRead, }, { href: "/permissions", icon: Shield, label: "权限列表", requiredScope: ScopePermissionRead, }, ], }, ] // Main Navigation Component export default function Navigation() { const [collapsed, setCollapsed] = useState(false) const pathname = usePathname() const isActive = (path: string) => { if (path === "/") { return pathname === path } return pathname === path || pathname.startsWith(path + "/") } const contextValue: NavigationContextType = { collapsed, pathname, isActive, } return ( ) }