优化后台侧栏导航分类

This commit is contained in:
yml2213
2026-06-07 10:42:31 +08:00
parent 8e7c181b27
commit 53eb4acad8
+185 -32
View File
@@ -1,25 +1,32 @@
<script setup lang="ts">
import {
Bell,
Briefcase,
ChatDotRound,
Coin,
DataLine,
Document,
DocumentChecked,
Operation,
Fold,
Expand,
Fold,
House,
Lock,
Money,
Operation,
ScaleToOriginal,
Service,
Shop,
Setting,
SwitchButton,
Tickets,
Tools,
User,
UserFilled,
Wallet,
Setting,
CreditCard
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { ElMessage, ElSubMenu } from 'element-plus'
import type { Component } from 'vue'
import { computed, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
@@ -35,37 +42,112 @@ const updatingStatus = ref(false)
interface NavItem {
label: string
to: string
icon: any
icon: Component
permission?: string
}
const allNavItems: NavItem[] = [
{ label: '仪表盘', to: '/admin/dashboard', icon: DataLine, permission: 'dashboard:view' },
{ label: '用户管理', to: '/admin/users', icon: User, permission: 'user:view' },
{ label: '订单管理', to: '/admin/orders', icon: Tickets, permission: 'order:view' },
{ label: '商品管理', to: '/admin/listings', icon: Shop, permission: 'listing:view' },
{ label: '商品审核', to: '/admin/listings/review', icon: DocumentChecked, permission: 'listing:approve' },
{ label: '仲裁中心', to: '/admin/disputes', icon: ScaleToOriginal, permission: 'dispute:view' },
{ label: '客服群聊', to: '/admin/chats', icon: ChatDotRound, permission: 'chat:view' },
{ label: '资金流水', to: '/admin/wallet-ledger', icon: Wallet, permission: 'wallet:view' },
{ label: '提现审核', to: '/admin/withdrawals', icon: Money, permission: 'withdrawal:list' },
{ label: '支付配置', to: '/admin/payment-configs', icon: CreditCard, permission: 'payment_config:list' },
{ label: '公告管理', to: '/admin/announcements', icon: Bell, permission: 'announcement:view' },
{ label: '系统配置', to: '/admin/system-configs', icon: Operation, permission: 'system_config:view' },
{ label: '审计日志', to: '/admin/audit-logs', icon: Document, permission: 'audit_log:view' },
{ label: '管理员管理', to: '/admin/admin-users', icon: UserFilled, permission: 'admin_user:manage' },
{ label: '角色管理', to: '/admin/roles', icon: Setting, permission: 'role:manage' },
interface NavGroup {
label: string
index: string
icon: Component
children: NavItem[]
}
const allNavGroups: NavGroup[] = [
{
label: '工作台',
index: 'workspace',
icon: House,
children: [
{ label: '仪表盘', to: '/admin/dashboard', icon: DataLine, permission: 'dashboard:view' },
],
},
{
label: '业务管理',
index: 'business',
icon: Briefcase,
children: [
{ label: '用户管理', to: '/admin/users', icon: User, permission: 'user:view' },
{ label: '订单管理', to: '/admin/orders', icon: Tickets, permission: 'order:view' },
{ label: '商品管理', to: '/admin/listings', icon: Shop, permission: 'listing:view' },
{ label: '商品审核', to: '/admin/listings/review', icon: DocumentChecked, permission: 'listing:approve' },
],
},
{
label: '客服与风控',
index: 'support-risk',
icon: Service,
children: [
{ label: '仲裁中心', to: '/admin/disputes', icon: ScaleToOriginal, permission: 'dispute:view' },
{ label: '客服群聊', to: '/admin/chats', icon: ChatDotRound, permission: 'chat:view' },
],
},
{
label: '财务管理',
index: 'finance',
icon: Coin,
children: [
{ label: '资金流水', to: '/admin/wallet-ledger', icon: Wallet, permission: 'wallet:view' },
{ label: '提现审核', to: '/admin/withdrawals', icon: Money, permission: 'withdrawal:list' },
{ label: '支付配置', to: '/admin/payment-configs', icon: CreditCard, permission: 'payment_config:list' },
],
},
{
label: '内容与配置',
index: 'content-config',
icon: Tools,
children: [
{ label: '公告管理', to: '/admin/announcements', icon: Bell, permission: 'announcement:view' },
{ label: '系统配置', to: '/admin/system-configs', icon: Operation, permission: 'system_config:view' },
],
},
{
label: '系统权限',
index: 'system-auth',
icon: Lock,
children: [
{ label: '审计日志', to: '/admin/audit-logs', icon: Document, permission: 'audit_log:view' },
{ label: '管理员管理', to: '/admin/admin-users', icon: UserFilled, permission: 'admin_user:manage' },
{ label: '角色管理', to: '/admin/roles', icon: Setting, permission: 'role:manage' },
],
},
]
const navItems = computed(() => {
if (adminSession.isSuperAdmin) return allNavItems
return allNavItems.filter((item) => {
if (!item.permission) return true
return adminSession.hasPermission(item.permission)
})
const allNavItems = allNavGroups.flatMap((group) => group.children)
function canAccessNavItem(item: NavItem) {
if (adminSession.isSuperAdmin) return true
if (!item.permission) return true
return adminSession.hasPermission(item.permission)
}
const navGroups = computed(() => {
return allNavGroups
.map((group) => ({
...group,
children: group.children.filter((item) => canAccessNavItem(item)),
}))
.filter((group) => group.children.length > 0)
})
const activeMenu = computed(() => {
const currentPath = route.path
const matchedItem = allNavItems
.slice()
.sort((a, b) => b.to.length - a.to.length)
.find((item) => currentPath === item.to || currentPath.startsWith(`${item.to}/`))
return matchedItem?.to || currentPath
})
const defaultOpeneds = computed(() => {
const activeGroup = allNavGroups.find((group) =>
group.children.some((item) => item.to === activeMenu.value)
)
return activeGroup ? [activeGroup.index] : []
})
const activeMenu = computed(() => route.path)
const adminName = computed(() => adminSession.nickname || adminSession.username || '管理员')
const supportStatus = computed(() => adminSession.supportStatus || 'offline')
const hasChatPermission = computed(() => adminSession.hasPermission('chat:view'))
@@ -124,15 +206,28 @@ async function handleLogout() {
<el-menu
:default-active="activeMenu"
:default-openeds="defaultOpeneds"
:collapse="isCollapsed"
:collapse-transition="false"
unique-opened
router
class="admin-menu"
>
<el-menu-item v-for="item in navItems" :key="item.to" :index="item.to">
<el-icon><component :is="item.icon" /></el-icon>
<template #title>{{ item.label }}</template>
</el-menu-item>
<el-sub-menu
v-for="group in navGroups"
:key="group.index"
:index="group.index"
popper-class="admin-menu-popper"
>
<template #title>
<el-icon><component :is="group.icon" /></el-icon>
<span>{{ group.label }}</span>
</template>
<el-menu-item v-for="item in group.children" :key="item.to" :index="item.to">
<el-icon><component :is="item.icon" /></el-icon>
<template #title>{{ item.label }}</template>
</el-menu-item>
</el-sub-menu>
</el-menu>
</aside>
@@ -259,6 +354,11 @@ async function handleLogout() {
}
.admin-menu {
--el-menu-bg-color: transparent;
--el-menu-text-color: #bfcbd9;
--el-menu-active-color: #409eff;
--el-menu-hover-bg-color: #263445;
flex: 1;
min-height: 0;
border-right: none;
@@ -271,6 +371,22 @@ async function handleLogout() {
width: 100%;
}
:deep(.el-menu) {
background-color: transparent;
}
:deep(.el-sub-menu__title) {
color: #bfcbd9;
}
:deep(.el-sub-menu__title:hover) {
background-color: #263445;
}
:deep(.el-sub-menu.is-active > .el-sub-menu__title) {
color: #409eff;
}
:deep(.el-menu-item) {
color: #bfcbd9;
}
@@ -284,6 +400,43 @@ async function handleLogout() {
background-color: #263445;
}
:deep(.el-menu--inline) {
background-color: #263445;
}
:deep(.el-menu--inline .el-menu-item) {
height: 46px;
background-color: #263445;
font-size: 14px;
}
:deep(.el-menu--inline .el-menu-item:hover),
:deep(.el-menu--inline .el-menu-item.is-active) {
background-color: #1f2d3d;
}
:global(.admin-menu-popper) {
--el-menu-bg-color: #304156;
--el-menu-text-color: #bfcbd9;
--el-menu-active-color: #409eff;
--el-menu-hover-bg-color: #263445;
}
:global(.admin-menu-popper .el-menu) {
border-right: none;
background-color: #304156;
}
:global(.admin-menu-popper .el-menu-item) {
color: #bfcbd9;
}
:global(.admin-menu-popper .el-menu-item:hover),
:global(.admin-menu-popper .el-menu-item.is-active) {
color: #409eff;
background-color: #263445;
}
.admin-workspace {
flex: 1;
min-width: 0;