左侧导航烂优化
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
Box,
|
||||
@@ -7,10 +7,13 @@ import {
|
||||
Connection,
|
||||
DataAnalysis,
|
||||
Document,
|
||||
Expand,
|
||||
Fold,
|
||||
List,
|
||||
Message,
|
||||
Service,
|
||||
Setting,
|
||||
SwitchButton,
|
||||
Tickets,
|
||||
User,
|
||||
} from '@element-plus/icons-vue'
|
||||
@@ -22,6 +25,10 @@ import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const sidebarStorageKey = 'admin-sidebar-collapsed'
|
||||
const isSidebarCollapsed = ref(
|
||||
typeof window !== 'undefined' && window.localStorage.getItem(sidebarStorageKey) === '1',
|
||||
)
|
||||
|
||||
const currentRole = computed(() => getAdminRole())
|
||||
const isAdmin = computed(() => currentRole.value === 'admin')
|
||||
@@ -71,6 +78,13 @@ const navItems = computed(() => {
|
||||
return items
|
||||
})
|
||||
|
||||
function toggleSidebarCollapse() {
|
||||
isSidebarCollapsed.value = !isSidebarCollapsed.value
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(sidebarStorageKey, isSidebarCollapsed.value ? '1' : '0')
|
||||
}
|
||||
}
|
||||
|
||||
async function submitLogout() {
|
||||
try {
|
||||
await logoutAdmin()
|
||||
@@ -85,14 +99,26 @@ async function submitLogout() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="admin-page">
|
||||
<div class="admin-page" :class="{ 'is-sidebar-collapsed': isSidebarCollapsed }">
|
||||
<aside class="admin-sidebar">
|
||||
<div class="sidebar-brand">
|
||||
<strong>运营后台</strong>
|
||||
<p>订单与交付管理</p>
|
||||
<div v-if="!isSidebarCollapsed" class="brand-copy">
|
||||
<strong>运营后台</strong>
|
||||
<p>订单与交付管理</p>
|
||||
</div>
|
||||
<el-tooltip :content="isSidebarCollapsed ? '展开导航' : '折叠导航'" placement="right">
|
||||
<el-button
|
||||
class="sidebar-toggle"
|
||||
circle
|
||||
:aria-label="isSidebarCollapsed ? '展开导航' : '折叠导航'"
|
||||
@click="toggleSidebarCollapse"
|
||||
>
|
||||
<el-icon><component :is="isSidebarCollapsed ? Expand : Fold" /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-user">
|
||||
<div v-if="!isSidebarCollapsed" class="sidebar-user">
|
||||
<div class="user-name">{{ getAdminUsername() || '未读取' }}</div>
|
||||
<div class="user-role">{{ roleLabel }}</div>
|
||||
<div class="user-expiry">有效期至 {{ formatAdminDateTime(getAdminTokenExpiresAt()) }}</div>
|
||||
@@ -102,15 +128,27 @@ async function submitLogout() {
|
||||
:default-active="route.path"
|
||||
router
|
||||
class="sidebar-menu"
|
||||
:collapse="isSidebarCollapsed"
|
||||
:collapse-transition="false"
|
||||
:ellipsis="false"
|
||||
>
|
||||
<el-menu-item v-for="item in navItems" :key="item.to" :index="item.to">
|
||||
<el-menu-item v-for="item in navItems" :key="item.to" :index="item.to" :title="item.label">
|
||||
<el-icon><component :is="item.icon" /></el-icon>
|
||||
<span>{{ item.label }}</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
|
||||
<el-button round class="logout-btn" @click="submitLogout">退出登录</el-button>
|
||||
<el-tooltip :disabled="!isSidebarCollapsed" content="退出登录" placement="right">
|
||||
<el-button
|
||||
class="logout-btn"
|
||||
:circle="isSidebarCollapsed"
|
||||
:round="!isSidebarCollapsed"
|
||||
@click="submitLogout"
|
||||
>
|
||||
<el-icon v-if="isSidebarCollapsed"><SwitchButton /></el-icon>
|
||||
<span v-else>退出登录</span>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</aside>
|
||||
|
||||
<section class="admin-content">
|
||||
@@ -123,13 +161,18 @@ async function submitLogout() {
|
||||
.admin-page {
|
||||
height: 100vh;
|
||||
display: grid;
|
||||
grid-template-columns: 260px minmax(0, 1fr);
|
||||
grid-template-columns: 232px minmax(0, 1fr);
|
||||
overflow: hidden;
|
||||
transition: grid-template-columns 0.18s ease;
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(73, 136, 255, 0.1), transparent 30%),
|
||||
linear-gradient(180deg, var(--bg-page) 0%, #edf3fb 100%);
|
||||
}
|
||||
|
||||
.admin-page.is-sidebar-collapsed {
|
||||
grid-template-columns: 72px minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.admin-sidebar {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
@@ -142,22 +185,36 @@ async function submitLogout() {
|
||||
}
|
||||
|
||||
.sidebar-brand {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
padding: 0 var(--space-5);
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.sidebar-brand strong {
|
||||
.brand-copy { min-width: 0; }
|
||||
|
||||
.brand-copy strong {
|
||||
display: block;
|
||||
font-size: var(--text-xl);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.sidebar-brand p {
|
||||
.brand-copy p {
|
||||
margin: var(--space-2) 0 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
flex: 0 0 auto;
|
||||
color: var(--text-secondary);
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
}
|
||||
|
||||
.sidebar-user {
|
||||
margin: 0 var(--space-4) var(--space-4);
|
||||
padding: var(--space-3);
|
||||
@@ -186,6 +243,7 @@ async function submitLogout() {
|
||||
border-right: none;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-menu-item) {
|
||||
@@ -205,6 +263,32 @@ async function submitLogout() {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .admin-sidebar {
|
||||
align-items: stretch;
|
||||
padding-top: var(--space-5);
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .sidebar-brand {
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
margin-bottom: var(--space-5);
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item) {
|
||||
justify-content: center;
|
||||
margin: 4px 10px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item .el-icon) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .logout-btn {
|
||||
width: 40px;
|
||||
margin: var(--space-3) auto 0;
|
||||
}
|
||||
|
||||
.admin-content {
|
||||
min-width: 0;
|
||||
height: 100vh;
|
||||
@@ -220,6 +304,10 @@ async function submitLogout() {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.admin-page.is-sidebar-collapsed {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.admin-sidebar {
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
@@ -228,8 +316,18 @@ async function submitLogout() {
|
||||
padding-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .admin-sidebar {
|
||||
padding-top: var(--space-4);
|
||||
}
|
||||
|
||||
.sidebar-menu { overflow: visible; }
|
||||
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item) {
|
||||
justify-content: flex-start;
|
||||
margin: 2px var(--space-2);
|
||||
padding: 0 var(--space-5);
|
||||
}
|
||||
|
||||
.admin-content {
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
|
||||
Reference in New Issue
Block a user