优化后台侧栏导航分类
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user