更新navigation里的权限控制 & 更新客户认领查询逻辑

This commit is contained in:
Eamon
2026-04-01 13:14:28 +08:00
parent be03cf6440
commit 545435d095
6 changed files with 261 additions and 215 deletions

View File

@@ -23,6 +23,7 @@ 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"
@@ -32,6 +33,21 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
import {
ScopeAdminRead,
ScopeAdminRoleRead,
ScopeBatchRead,
ScopeBillRead,
ScopeChannelRead,
ScopeCouponRead,
ScopeDiscountRead,
ScopePermissionRead,
ScopeProductRead,
ScopeResourceRead,
ScopeTradeRead,
ScopeUserRead,
ScopeUserReadOne,
} from "@/lib/scopes"
// Navigation Context
interface NavigationContextType {
@@ -78,13 +94,16 @@ interface NavItemProps {
href: string
icon: LucideIcon
label: string
requiredScope?: string
}
function NavItem({ href, icon: Icon, label }: NavItemProps) {
function NavItem({ href, icon: Icon, label, requiredScope }: NavItemProps) {
// console.log(requiredScope, "requiredScope")
const { collapsed, isActive } = useNavigation()
const active = isActive(href)
const linkContent = (
let linkContent = (
<Link
href={href}
className={`flex items-center ${
@@ -101,19 +120,25 @@ function NavItem({ href, icon: Icon, label }: NavItemProps) {
)
if (collapsed) {
return (
<li>
<Tooltip>
<TooltipTrigger asChild>{linkContent}</TooltipTrigger>
<TooltipContent side="right">
<p>{label}</p>
</TooltipContent>
</Tooltip>
</li>
linkContent = (
<Tooltip>
<TooltipTrigger asChild>{linkContent}</TooltipTrigger>
<TooltipContent side="right">
<p>{label}</p>
</TooltipContent>
</Tooltip>
)
}
return <li>{linkContent}</li>
if (requiredScope) {
linkContent = (
<Auth scope={requiredScope}>
<li>{linkContent}</li>
</Auth>
)
}
return linkContent
}
// NavSeparator Component
@@ -129,6 +154,109 @@ function NavSeparator() {
)
}
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: ScopeUserReadOne,
},
{
href: "/cust",
icon: ContactRound,
label: "客户管理",
requiredScope: ScopeUserRead,
},
{
href: "/trade",
icon: Activity,
label: "交易明细",
requiredScope: ScopeTradeRead,
},
{
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: Code,
label: "IP管理",
requiredScope: ScopeChannelRead,
},
],
},
{
title: "系统",
items: [
{
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)
@@ -168,56 +296,16 @@ export default function Navigation() {
{/* Navigation Menu */}
<ScrollArea className="flex-1 py-3">
<nav className="space-y-3">
{/* 概览 */}
<NavGroup title="概览">
<NavItem href="/" icon={Home} label="首页" />
<NavItem href="/statistics" icon={BarChart3} label="数据统计" />
</NavGroup>
{/*<NavSeparator />*/}
{/* IP 资源 */}
{/*<NavGroup title="IP 资源">
<NavItem href="/proxy/nodes" icon={Globe} label="节点列表" />
<NavItem href="/proxy/pools" icon={Server} label="IP池管理" />
</NavGroup>*/}
<NavSeparator />
{/* 客户 */}
<NavGroup title="客户">
<NavItem href="/user" icon={Users} label="客户认领" />
<NavItem href="/cust" icon={ContactRound} label="客户管理" />
<NavItem href="/trade" icon={Activity} label="交易明细" />
<NavItem href="/billing" icon={DollarSign} label="账单详情" />
</NavGroup>
<NavSeparator />
{/* 运营 */}
<NavGroup title="运营">
<NavItem href="/product" icon={ShoppingBag} label="产品管理" />
<NavItem
href="/discount"
icon={SquarePercent}
label="折扣管理"
/>
<NavItem href="/coupon" icon={TicketPercent} label="优惠券" />
<NavItem href="/resources" icon={Package} label="套餐管理" />
<NavItem href="/batch" icon={ClipboardList} label="提取记录" />
<NavItem href="/channel" icon={Code} label="IP管理" />
</NavGroup>
<NavSeparator />
{/* 系统 */}
<NavGroup title="系统">
{/*<NavItem href="/settings" icon={Settings} label="系统设置" />*/}
<NavItem href="/admin" icon={Shield} label="管理员" />
<NavItem href="/roles" icon={KeyRound} label="角色列表" />
<NavItem href="/permissions" icon={Shield} label="权限列表" />
{/*<NavItem href="/logs" icon={FileText} label="系统日志" />*/}
</NavGroup>
{menuSections.map((section, idx) => (
<div key={section.title}>
<NavGroup title={section.title}>
{section.items.map(item => (
<NavItem key={item.label} {...item} />
))}
</NavGroup>
{idx !== menuSections.length - 1 && <NavSeparator />}
</div>
))}
</nav>
</ScrollArea>