- 新增 _mixins.scss,统一 app-main / sidebar-scroll 高度计算 - _theme.scss 引入 SCSS 颜色令牌,menu-hover 改用 color-mix() 自动派生 - _variables.scss 新增 $sidebar-toggle-height 替代魔法数字 50px - LeftLayout / TopLayout / MixLayout 中重复 calc 替换为 mixin 调用 - 修复 apifox / internal-doc demo 页面 tags-view 高度错误(34px→40px) - 添加主题变量契约注释,方便后续新增主题
140 lines
2.9 KiB
Vue
140 lines
2.9 KiB
Vue
<template>
|
|
<BaseLayout>
|
|
<!-- 左侧菜单 -->
|
|
<div
|
|
v-show="!appStore.contentFullscreen"
|
|
class="layout__sidebar"
|
|
:class="{ 'layout__sidebar--collapsed': !isSidebarOpen }"
|
|
>
|
|
<div :class="{ 'has-logo': showLogo }" class="layout-sidebar">
|
|
<LayoutLogo v-if="showLogo" :collapse="!isSidebarOpen" />
|
|
<el-scrollbar>
|
|
<LayoutSidebar :data="routes" base-path="" />
|
|
</el-scrollbar>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 主内容区 -->
|
|
<div
|
|
class="layout__main"
|
|
:class="{
|
|
hasTagsView: showTagsView,
|
|
'layout__main--collapsed': !isSidebarOpen,
|
|
'layout__main--fullscreen': appStore.contentFullscreen,
|
|
}"
|
|
>
|
|
<LayoutNavbar v-show="!appStore.contentFullscreen" />
|
|
<LayoutTagsView v-if="showTagsView" />
|
|
<LayoutMain />
|
|
</div>
|
|
</BaseLayout>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useLayout } from "./useLayout";
|
|
import { useAppStore } from "@/stores";
|
|
import BaseLayout from "./BaseLayout.vue";
|
|
import LayoutLogo from "./components/LayoutLogo.vue";
|
|
import LayoutNavbar from "./components/LayoutNavbar.vue";
|
|
import LayoutTagsView from "./components/LayoutTagsView.vue";
|
|
import LayoutMain from "./components/LayoutMain.vue";
|
|
import LayoutSidebar from "./components/LayoutSidebar.vue";
|
|
|
|
const { showTagsView, showLogo, isSidebarOpen, routes } = useLayout();
|
|
const appStore = useAppStore();
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@use "@/styles/base/mixins" as *;
|
|
|
|
.layout {
|
|
&__sidebar {
|
|
position: fixed;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
z-index: 999;
|
|
width: $sidebar-width;
|
|
background-color: $menu-background;
|
|
transition: width 0.28s;
|
|
|
|
&--collapsed {
|
|
width: $sidebar-width-collapsed;
|
|
}
|
|
|
|
.layout-sidebar {
|
|
position: relative;
|
|
height: 100%;
|
|
background-color: var(--menu-background);
|
|
border-right: 1px solid var(--card-border);
|
|
transition: width 0.28s;
|
|
|
|
&.has-logo {
|
|
.el-scrollbar {
|
|
@include sidebar-scroll-height-with-logo;
|
|
}
|
|
}
|
|
|
|
:deep(.el-menu) {
|
|
border: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
&__main {
|
|
position: relative;
|
|
height: 100%;
|
|
margin-left: $sidebar-width;
|
|
overflow-y: auto;
|
|
transition: margin-left 0.28s;
|
|
|
|
&--collapsed {
|
|
margin-left: $sidebar-width-collapsed;
|
|
}
|
|
|
|
&--fullscreen {
|
|
margin-left: 0 !important;
|
|
}
|
|
|
|
.fixed-header {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 9;
|
|
transition: width 0.28s;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 移动端样式*/
|
|
.mobile {
|
|
.layout__sidebar {
|
|
width: $sidebar-width !important;
|
|
transition:
|
|
transform 0.28s,
|
|
width 0s;
|
|
}
|
|
|
|
&.hideSidebar {
|
|
.layout__sidebar {
|
|
transform: translateX(-$sidebar-width);
|
|
}
|
|
}
|
|
|
|
&.openSidebar {
|
|
.layout__sidebar {
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
.layout__main {
|
|
margin-left: 0 !important;
|
|
}
|
|
}
|
|
|
|
.hasTagsView {
|
|
:deep(.app-main) {
|
|
@include app-main-height-with-tags;
|
|
}
|
|
}
|
|
</style>
|