financial_system/frontend/src/components/SidebarNav.vue
2026-06-18 13:21:20 +08:00

117 lines
2.7 KiB
Vue

<script setup lang="ts">
import {
Banknote,
BadgeDollarSign,
Building2,
ClipboardList,
FileChartColumn,
LayoutDashboard,
LogOut,
Network,
PanelLeftClose,
PanelLeftOpen,
ScrollText,
Settings2,
HandCoins,
UserCog,
UsersRound,
} from "@lucide/vue";
import { computed } from "vue";
import { useRouter } from "vue-router";
import { useAuthStore } from "../stores/auth";
defineProps<{
collapsed: boolean;
open: boolean;
}>();
const emit = defineEmits<{
close: [];
"toggle-collapse": [];
}>();
const auth = useAuthStore();
const router = useRouter();
const backendIconMap = {
payroll: Banknote,
jobs: ClipboardList,
employees: UserCog,
organization: Network,
salary_profiles: BadgeDollarSign,
commissions: HandCoins,
reports: FileChartColumn,
configs: Settings2,
users: UsersRound,
operation_logs: ScrollText,
};
const menuItems = computed(() => [
{
code: "dashboard",
name: "工作台",
path: "/dashboard",
icon: LayoutDashboard,
},
...auth.menus.map((menu) => ({
...menu,
icon: backendIconMap[menu.code as keyof typeof backendIconMap] || ClipboardList,
})),
]);
function logout(): void {
auth.logout();
emit("close");
router.push("/login");
}
</script>
<template>
<aside class="sidebar" :class="{ 'is-open': open }">
<div class="brand">
<div class="brand-main">
<div class="brand-mark">
<Building2 :size="22" aria-hidden="true" />
</div>
<div class="brand-copy">
<p class="brand-title">企业薪酬管理</p>
<p class="brand-subtitle">管理门户</p>
</div>
</div>
</div>
<nav class="sidebar-nav" aria-label="主导航">
<RouterLink
v-for="item in menuItems"
:key="item.code"
:to="item.path"
class="nav-link"
active-class="is-active"
:title="item.name"
@click="emit('close')"
>
<component :is="item.icon" :size="21" aria-hidden="true" />
<span>{{ item.name }}</span>
</RouterLink>
</nav>
<div class="sidebar-footer">
<button
class="nav-link nav-button"
type="button"
:title="collapsed ? '展开侧边栏' : '收起侧边栏'"
@click="emit('toggle-collapse')"
>
<PanelLeftOpen v-if="collapsed" :size="21" aria-hidden="true" />
<PanelLeftClose v-else :size="21" aria-hidden="true" />
<span>{{ collapsed ? "展开侧栏" : "收起侧栏" }}</span>
</button>
<button class="nav-link nav-button danger" type="button" title="退出登录" @click="logout">
<LogOut :size="21" aria-hidden="true" />
<span>退出登录</span>
</button>
</div>
</aside>
</template>