Files
education/frontend/src/layout/index.vue
T
2026-08-21 18:42:51 +08:00

190 lines
4.4 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, '--current-color-light': theme + '1a', '--current-color-dark-bg': theme + '33'}">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<!-- 顶部全宽 Header -->
<div class="top-header">
<div class="top-header__left">
<hamburger
v-if="device === 'mobile'"
id="mobile-hamburger"
:is-active="sidebar.opened"
class="mobile-hamburger"
@toggleClick="toggleSideBar"
/>
<span class="sys-title">教学管理信息系统</span>
</div>
<semester-bar class="top-header__center" />
<navbar class="top-header__right" @setLayout="setLayout" :header-mode="true" />
</div>
<!-- 下方:侧边栏 + 主内容 -->
<div class="lower-container" :class="{sidebarHide:sidebar.hide}">
<sidebar v-if="!sidebar.hide" class="sidebar-container"/>
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
<tags-view v-if="needTagsView"/>
<app-main/>
<settings ref="settingRef"/>
</div>
</div>
</div>
</template>
<script>
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
import SemesterBar from './components/SemesterBar'
import Hamburger from '@/components/Hamburger'
import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex'
import variables from '@/assets/styles/variables.scss'
export default {
name: 'Layout',
components: {
AppMain,
Navbar,
Settings,
Sidebar,
TagsView,
SemesterBar,
Hamburger
},
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
}),
classObj() {
return {
hideSidebar: !this.sidebar.opened,
mobile: this.device === 'mobile'
}
},
variables() {
return variables
}
},
methods: {
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
},
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},
setLayout() {
this.$refs.settingRef.openSetting()
}
}
}
</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%;
display: flex;
flex-direction: column;
}
/* 顶部全宽 Header */
.top-header {
flex-shrink: 0;
height: 60px;
display: flex;
align-items: center;
background: var(--edu-green-primary);
background: linear-gradient(90deg, var(--edu-green-primary) 0%, var(--edu-green-dark) 100%);
box-shadow: 0 2px 8px rgba(0, 21, 41, 0.16);
padding: 0 20px;
z-index: 10;
&__left {
display: flex;
align-items: center;
flex-shrink: 0;
height: 100%;
gap: 14px;
.mobile-hamburger {
display: flex;
align-items: center;
justify-content: center;
height: 36px;
width: 36px;
border-radius: 8px;
cursor: pointer;
color: #fff;
transition: background 0.25s ease;
&:hover {
background: rgba(255, 255, 255, 0.15);
}
}
.sys-title {
font-size: 19px;
font-weight: 700;
color: #fff;
white-space: nowrap;
letter-spacing: 1.5px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}
}
&__center {
flex: 1;
min-width: 0;
display: flex;
justify-content: center;
height: 100%;
}
&__right {
flex-shrink: 0;
height: 100%;
}
}
/* 下方主体 */
.lower-container {
flex: 1;
min-height: 0;
display: flex;
position: relative;
}
.sidebar-container {
flex-shrink: 0;
}
.main-container {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
height: 100%;
background-color: #f5f7fa;
}
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
</style>