文件
hyb-oa/client/src/components/navigation/NavLinks.tsx
T

166 行
4.0 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;
icon: string;
anyOf?: string[];
};
export const NAV_ITEMS: NavItem[] = [
{ to: "/dashboard", label: "仪表盘", icon: "dashboard" },
{
to: "/reimbursements",
label: "我的报销",
icon: "request_quote",
anyOf: ["expense.view_own", "expense.view_all"],
},
{
to: "/leave-requests",
label: "请假申请",
icon: "event_available",
anyOf: ["leave.view_own", "leave.view_all"],
},
{
to: "/purchase-requests",
label: "采购申请",
icon: "shopping_cart",
anyOf: ["procurement.create", "procurement.view_own", "procurement.view_all", "procurement.manage"],
},
{
to: "/workflow/tasks",
label: "待我处理",
icon: "fact_check",
anyOf: ["expense.approve", "leave.approve", "procurement.approve"],
},
{
to: "/assets",
label: "资产台账",
icon: "inventory_2",
anyOf: ["asset.view_own", "asset.view_all", "asset.manage", "asset.transfer", "asset.inventory"],
},
{
to: "/inventory-checks",
label: "资产盘点",
icon: "fact_check",
anyOf: ["asset.inventory"],
},
{
to: "/invoice-pool",
label: "票据中心",
icon: "receipt_long",
anyOf: ["invoice.upload", "invoice.view_own", "invoice.manage"],
},
{
to: "/mobile/capture",
label: "移动拍照",
icon: "document_scanner",
anyOf: ["invoice.upload", "invoice.manage"],
},
{
to: "/mobile/approvals",
label: "移动审批",
icon: "mobile_friendly",
anyOf: ["expense.approve", "leave.approve", "procurement.approve"],
},
{
to: "/budgets",
label: "预算管理",
icon: "account_balance",
anyOf: ["budget.view", "budget.manage"],
},
{
to: "/audit-logs",
label: "审计工作台",
icon: "manage_search",
anyOf: ["system.audit.view"],
},
{
to: "/delegations",
label: "委派管理",
icon: "swap_horiz",
anyOf: ["expense.proxy_manage"],
},
{
to: "/system/users",
label: "用户管理",
icon: "group",
anyOf: ["system.users"],
},
{
to: "/system/departments",
label: "部门管理",
icon: "account_tree",
anyOf: ["system.users"],
},
{
to: "/system/master-data",
label: "主数据",
icon: "dataset",
anyOf: ["masterdata.view", "masterdata.manage"],
},
{
to: "/system/notification-channels",
label: "通知渠道",
icon: "notifications_active",
anyOf: ["notification.channel.manage"],
},
{
to: "/system/integrations/erp",
label: "ERP 集成",
icon: "hub",
anyOf: ["integration.manage"],
},
{
to: "/system/approval-rules",
label: "审批规则",
icon: "rule",
anyOf: ["system.settings"],
},
{
to: "/system/feature-flags",
label: "功能开关",
icon: "toggle_on",
anyOf: ["system.settings"],
},
{ to: "/settings/profile", label: "个人设置", icon: "manage_accounts" },
];
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(
"flex items-center gap-3 px-3 py-2 my-1 rounded-lg text-sm transition-colors",
isActive
? "bg-zinc-100 font-bold text-zinc-900"
: "font-medium text-zinc-600 hover:bg-zinc-50 hover:text-zinc-900",
)
}
>
<span className="material-symbols-outlined text-[20px]">{item.icon}</span>
<span>{item.label}</span>
</NavLink>
))}
</nav>
);
}