95 行
2.1 KiB
TypeScript
95 行
2.1 KiB
TypeScript
import { NavLink } from "react-router-dom";
|
|
import { useAuth } from "../../auth/AuthContext";
|
|
import { hasAnyPermission } from "../../auth/permissions";
|
|
import { cn } from "../../lib/utils";
|
|
|
|
export type NavItem = {
|
|
to: string;
|
|
label: string;
|
|
anyOf?: string[];
|
|
};
|
|
|
|
export const NAV_ITEMS: NavItem[] = [
|
|
{ to: "/dashboard", label: "仪表盘" },
|
|
{
|
|
to: "/reimbursements",
|
|
label: "我的报销",
|
|
anyOf: ["expense.view_own", "expense.view_all"],
|
|
},
|
|
{
|
|
to: "/workflow/tasks",
|
|
label: "待我处理",
|
|
anyOf: ["expense.approve"],
|
|
},
|
|
{
|
|
to: "/invoice-pool",
|
|
label: "票据中心",
|
|
anyOf: ["invoice.upload", "invoice.view_own", "invoice.manage"],
|
|
},
|
|
{
|
|
to: "/budgets",
|
|
label: "预算管理",
|
|
anyOf: ["budget.view", "budget.manage"],
|
|
},
|
|
{
|
|
to: "/audit-logs",
|
|
label: "审计工作台",
|
|
anyOf: ["system.audit.view"],
|
|
},
|
|
{
|
|
to: "/delegations",
|
|
label: "委派管理",
|
|
anyOf: ["expense.proxy_manage"],
|
|
},
|
|
{
|
|
to: "/system/users",
|
|
label: "用户管理",
|
|
anyOf: ["system.users"],
|
|
},
|
|
{
|
|
to: "/system/departments",
|
|
label: "部门管理",
|
|
anyOf: ["system.users"],
|
|
},
|
|
{
|
|
to: "/system/approval-rules",
|
|
label: "审批规则",
|
|
anyOf: ["system.settings"],
|
|
},
|
|
{ to: "/settings/profile", label: "个人设置" },
|
|
];
|
|
|
|
export function NavLinks({ onNavigate }: { onNavigate?: () => void }) {
|
|
const { permissions } = useAuth();
|
|
|
|
const visibleItems = NAV_ITEMS.filter((item) => {
|
|
if (!item.anyOf) {
|
|
return true;
|
|
}
|
|
|
|
return hasAnyPermission(permissions, item.anyOf);
|
|
});
|
|
|
|
return (
|
|
<nav className="space-y-1">
|
|
{visibleItems.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
onClick={() => onNavigate?.()}
|
|
className={({ isActive }) =>
|
|
cn(
|
|
"block rounded-lg px-3 py-2.5 text-sm font-medium transition-colors",
|
|
isActive
|
|
? "bg-primary-50 text-primary"
|
|
: "text-slate-700 hover:bg-slate-50 hover:text-slate-900",
|
|
)
|
|
}
|
|
>
|
|
{item.label}
|
|
</NavLink>
|
|
))}
|
|
</nav>
|
|
);
|
|
}
|