fastbee/yack-web/src/layout/index.vue

204 lines
5.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<!-- 顶部浏览器式标签栏:固定在页面最上方,左侧是 logo 区(与侧边栏同宽同色) -->
<div
v-if="needTagsView"
class="top-tabs-bar"
:class="sideTheme === 'theme-dark' ? 'is-dark' : 'is-light'"
:style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"
>
<logo v-if="showLogo && !sidebar.hide" class="top-tabs-logo" :collapse="!sidebar.opened" compact />
<tags-view class="top-tabs-view" />
</div>
<sidebar v-if="!sidebar.hide" class="sidebar-container" />
<div :class="{ sidebarHide: sidebar.hide }" class="main-container">
<div :class="{ 'fixed-header': fixedHeader }">
<navbar />
</div>
<app-main />
<right-panel>
<settings />
</right-panel>
</div>
</div>
</template>
<script>
import RightPanel from '@/components/RightPanel';
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components';
import Logo from './components/Sidebar/Logo';
import ResizeMixin from './mixin/ResizeHandler';
import { mapState } from 'vuex';
import variables from '@/assets/styles/variables.scss';
export default {
name: 'Layout',
components: {
AppMain,
Logo,
Navbar,
RightPanel,
Settings,
Sidebar,
TagsView,
},
mixins: [ResizeMixin],
computed: {
...mapState({
theme: (state) => state.settings.theme,
sideTheme: (state) => state.settings.sideTheme,
sidebar: (state) => state.app.sidebar,
device: (state) => state.app.device,
needTagsView: (state) => state.settings.tagsView,
fixedHeader: (state) => state.settings.fixedHeader,
showLogo: (state) => state.settings.sidebarLogo,
}),
classObj() {
return {
hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile',
'has-top-tabs': this.needTagsView,
};
},
variables() {
return variables;
},
},
methods: {
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false });
},
},
};
</script>
<style lang="scss" scoped>
@import '~@/assets/styles/mixin.scss';
@import '~@/assets/styles/variables.scss';
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
&.mobile.openSidebar {
position: fixed;
top: 0;
}
}
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
// 顶部浏览器式标签栏:整行固定,左侧 logo 区与侧边栏同宽
.top-tabs-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: $top-tabs-height;
display: flex;
align-items: stretch;
z-index: 1002;
// 不加投影:选中标签是白底,要与下方白色 navbar 无缝连成一体,投影会在接缝处压出一条暗线
// 深色侧边栏主题:深蓝底白字,选中标签白底 —— 正好与下方白色 navbar 连成一体
&.is-dark {
--top-tabs-fg: #ffffff;
--top-tabs-fg-dim: rgba(255, 255, 255, 0.7);
--top-tabs-hover: rgba(0, 0, 0, 0.06);
--top-tabs-line: rgba(255, 255, 255, 0.12);
--top-tabs-close-fg: rgba(255, 255, 255, 0.75);
--top-tabs-close-hover: rgba(255, 255, 255, 0.28);
--top-tabs-active-bg: #ffffff;
--top-tabs-active-fg: #303133;
--top-tabs-active-close-fg: #909399;
--top-tabs-active-close-hover: #dcdfe6;
}
// 浅色侧边栏主题:白底深字,选中标签用主题色实心块保证对比
&.is-light {
--top-tabs-fg: #303133;
--top-tabs-fg-dim: rgba(0, 0, 0, 0.65);
--top-tabs-hover: rgba(0, 0, 0, 0.05);
--top-tabs-line: rgba(0, 0, 0, 0.08);
--top-tabs-close-fg: #909399;
--top-tabs-close-hover: rgba(0, 0, 0, 0.12);
--top-tabs-active-bg: var(--current-color, #409eff);
--top-tabs-active-fg: #ffffff;
--top-tabs-active-close-fg: rgba(255, 255, 255, 0.85);
--top-tabs-active-close-hover: rgba(255, 255, 255, 0.3);
}
}
.top-tabs-logo {
flex: 0 0 auto;
width: $base-sidebar-width;
border-right: 1px solid var(--top-tabs-line);
transition: width 0.28s;
box-sizing: border-box;
}
.top-tabs-view {
flex: 1 1 auto;
min-width: 0;
}
// 侧边栏收起时 logo 区同步收窄(与 sidebar.scss 的 54px 保持一致)
.hideSidebar .top-tabs-logo {
width: 54px;
}
// 移动端屏宽有限,logo 区让位给标签(此时侧边栏内会重新显示 logo)
.mobile .top-tabs-logo {
display: none;
}
.withoutAnimation .top-tabs-logo {
transition: none;
}
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$base-sidebar-width});
transition: width 0.28s;
}
.hideSidebar .fixed-header {
width: calc(100% - 54px);
}
.sidebarHide .fixed-header {
width: 100%;
}
// 顶部标签栏占位:主内容整体下移,吸顶头部同步下移到标签栏下方
.has-top-tabs {
.main-container {
padding-top: $top-tabs-height;
}
.fixed-header {
top: $top-tabs-height;
}
}
.mobile .fixed-header {
width: 100%;
}
</style>