refactor(layout-sider): 重构侧边栏布局结构并调整折叠模式
1. 将侧边栏折叠模式从transform改为width 2. 简化DOM层级,移除多余的sider-wrapper容器 3. 调整用户区定位使其固定在侧边栏底部 4. 优化图标渲染参数和菜单样式封装
This commit is contained in:
parent
e0087b12a6
commit
4093c75241
|
|
@ -1,64 +1,60 @@
|
||||||
<template>
|
<template>
|
||||||
<n-layout-sider
|
<n-layout-sider
|
||||||
bordered
|
bordered
|
||||||
collapse-mode="transform"
|
collapse-mode="width"
|
||||||
:collapsed-width="64"
|
:collapsed-width="64"
|
||||||
:width="240"
|
:width="240"
|
||||||
:collapsed="layoutStore.siderCollapsed"
|
:collapsed="layoutStore.siderCollapsed"
|
||||||
:show-trigger="false"
|
:show-trigger="false"
|
||||||
class="layout-sider"
|
class="layout-sider"
|
||||||
>
|
>
|
||||||
<div class="sider-wrapper">
|
<!-- Logo -->
|
||||||
<!-- Logo -->
|
<div class="sider-logo" @click="router.push('/dashboard')">
|
||||||
<div class="sider-logo" @click="router.push('/dashboard')">
|
<div class="logo-icon">
|
||||||
<div class="logo-icon">
|
<svg viewBox="0 0 36 36" fill="none">
|
||||||
<svg viewBox="0 0 36 36" fill="none">
|
<rect width="36" height="36" rx="10" fill="url(#logo-grad)" />
|
||||||
<rect width="36" height="36" rx="10" fill="url(#logo-grad)" />
|
<path d="M10 24V12l8 7 8-7v12" stroke="#fff" stroke-width="2.5"
|
||||||
<path d="M10 24V12l8 7 8-7v12" stroke="#fff" stroke-width="2.5"
|
stroke-linecap="round" stroke-linejoin="round" />
|
||||||
stroke-linecap="round" stroke-linejoin="round" />
|
<defs>
|
||||||
<defs>
|
<linearGradient id="logo-grad" x1="0" y1="0" x2="36" y2="36">
|
||||||
<linearGradient id="logo-grad" x1="0" y1="0" x2="36" y2="36">
|
<stop stop-color="#0891B2" /><stop offset="1" stop-color="#06B6D4" />
|
||||||
<stop stop-color="#0891B2" /><stop offset="1" stop-color="#06B6D4" />
|
</linearGradient>
|
||||||
</linearGradient>
|
</defs>
|
||||||
</defs>
|
</svg>
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<transition name="fade-text">
|
|
||||||
<span v-if="!layoutStore.siderCollapsed" class="logo-text">DevBox</span>
|
|
||||||
</transition>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 菜单 -->
|
|
||||||
<div class="sider-menu">
|
|
||||||
<n-menu
|
|
||||||
:value="activeMenuKey"
|
|
||||||
:collapsed="layoutStore.siderCollapsed"
|
|
||||||
:collapsed-width="64"
|
|
||||||
:collapsed-icon-size="22"
|
|
||||||
:options="menuOptions"
|
|
||||||
:default-expanded-keys="['system']"
|
|
||||||
@update:value="onMenuSelect"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 用户区 -->
|
|
||||||
<transition name="fade-text">
|
<transition name="fade-text">
|
||||||
<div v-if="!layoutStore.siderCollapsed" class="sider-user">
|
<span v-if="!layoutStore.siderCollapsed" class="logo-text">DevBox</span>
|
||||||
<n-avatar round size="small" :style="{ backgroundColor: '#0891B2' }">
|
|
||||||
{{ userInitial }}
|
|
||||||
</n-avatar>
|
|
||||||
<div class="user-meta">
|
|
||||||
<span class="user-name">{{ username }}</span>
|
|
||||||
<span class="user-role">管理员</span>
|
|
||||||
</div>
|
|
||||||
<n-dropdown trigger="click" :options="userDropdownOptions" @select="onUserAction">
|
|
||||||
<n-button text size="tiny" class="user-more-btn">
|
|
||||||
<template #icon><n-icon :component="ChevronForward" /></template>
|
|
||||||
</n-button>
|
|
||||||
</n-dropdown>
|
|
||||||
</div>
|
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 菜单 -->
|
||||||
|
<n-menu
|
||||||
|
:value="activeMenuKey"
|
||||||
|
:collapsed="layoutStore.siderCollapsed"
|
||||||
|
:collapsed-width="64"
|
||||||
|
:collapsed-icon-size="22"
|
||||||
|
:options="menuOptions"
|
||||||
|
:default-expanded-keys="['system']"
|
||||||
|
@update:value="onMenuSelect"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 用户区 -->
|
||||||
|
<transition name="fade-text">
|
||||||
|
<div v-if="!layoutStore.siderCollapsed" class="sider-user">
|
||||||
|
<n-avatar round size="small" :style="{ backgroundColor: '#0891B2' }">
|
||||||
|
{{ userInitial }}
|
||||||
|
</n-avatar>
|
||||||
|
<div class="user-meta">
|
||||||
|
<span class="user-name">{{ username }}</span>
|
||||||
|
<span class="user-role">管理员</span>
|
||||||
|
</div>
|
||||||
|
<n-dropdown trigger="click" :options="userDropdownOptions" @select="onUserAction">
|
||||||
|
<n-button text size="tiny" class="user-more-btn">
|
||||||
|
<template #icon><n-icon :component="ChevronForward" /></template>
|
||||||
|
</n-button>
|
||||||
|
</n-dropdown>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
</n-layout-sider>
|
</n-layout-sider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -93,7 +89,7 @@ const userInitial = computed(() => username.charAt(0).toUpperCase())
|
||||||
|
|
||||||
// ─── Icon helper ───
|
// ─── Icon helper ───
|
||||||
function renderIcon(icon: Component) {
|
function renderIcon(icon: Component) {
|
||||||
return () => h(NIcon, { size: 18 }, { default: () => h(icon) })
|
return () => h(NIcon, null, { default: () => h(icon) })
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDropdownIcon(icon: Component) {
|
function renderDropdownIcon(icon: Component) {
|
||||||
|
|
@ -116,6 +112,7 @@ const menuOptions: MenuOption[] = [
|
||||||
{ key: 'plugin', label: '插件管理', icon: renderIcon(ExtensionPuzzleOutline), disabled: true },
|
{ key: 'plugin', label: '插件管理', icon: renderIcon(ExtensionPuzzleOutline), disabled: true },
|
||||||
{ key: 'settings', label: '系统设置', icon: renderIcon(SettingsOutline), disabled: true },
|
{ key: 'settings', label: '系统设置', icon: renderIcon(SettingsOutline), disabled: true },
|
||||||
]
|
]
|
||||||
|
|
||||||
const activeMenuKey = computed(() => route.path)
|
const activeMenuKey = computed(() => route.path)
|
||||||
|
|
||||||
function onMenuSelect(key: string) {
|
function onMenuSelect(key: string) {
|
||||||
|
|
@ -146,13 +143,6 @@ function onUserAction(key: string) {
|
||||||
--n-sider-border-color: var(--color-border, #E5E6EB);
|
--n-sider-border-color: var(--color-border, #E5E6EB);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sider-wrapper {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sider-logo {
|
.sider-logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -179,27 +169,16 @@ function onUserAction(key: string) {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sider-menu {
|
|
||||||
flex: 1;
|
|
||||||
overflow: visible;
|
|
||||||
padding: 8px;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sider-menu :deep(.n-menu) {
|
|
||||||
--n-item-height: 40px;
|
|
||||||
--n-border-radius: 6px;
|
|
||||||
--n-font-size: 14px;
|
|
||||||
--n-item-icon-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sider-user {
|
.sider-user {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
border-top: 1px solid var(--color-border, #E5E6EB);
|
border-top: 1px solid var(--color-border, #E5E6EB);
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-meta {
|
.user-meta {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue