2026-01-16 22:04:12 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="member-layout">
|
2026-04-07 11:01:11 +08:00
|
|
|
<el-container class="layout-container">
|
|
|
|
|
<el-header class="layout-header">
|
|
|
|
|
<Header />
|
|
|
|
|
</el-header>
|
2026-01-16 22:04:12 +08:00
|
|
|
<el-scrollbar :style="calcHeight(60)" class="main-scrollbar" ref="mainScrollbarRef">
|
2026-04-07 11:01:11 +08:00
|
|
|
<div class="layout-main">
|
|
|
|
|
<div class="layout-content">
|
|
|
|
|
<el-row class="layouts-main" justify="center">
|
|
|
|
|
<el-col class="user-layouts" :span="16" :xs="24">
|
|
|
|
|
<client-only>
|
|
|
|
|
<Aside class="hidden-sm-and-down" />
|
|
|
|
|
</client-only>
|
|
|
|
|
<el-main class="layout-main-content">
|
|
|
|
|
<slot />
|
|
|
|
|
</el-main>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
</div>
|
|
|
|
|
<Footer />
|
|
|
|
|
</div>
|
2026-01-16 22:04:12 +08:00
|
|
|
</el-scrollbar>
|
|
|
|
|
</el-container>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-04-07 11:01:11 +08:00
|
|
|
import { useTemplateRef, watch, provide } from 'vue'
|
2026-01-16 22:04:12 +08:00
|
|
|
import Header from './components/header.vue'
|
|
|
|
|
import Aside from './components/aside.vue'
|
|
|
|
|
import Footer from './components/footer.vue'
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
const mainScrollbarRef = useTemplateRef('mainScrollbarRef')
|
|
|
|
|
|
2026-04-07 11:01:11 +08:00
|
|
|
// 计算滚动区域高度
|
|
|
|
|
const calcHeight = (headerHeight: number) => {
|
|
|
|
|
return {
|
|
|
|
|
height: `calc(100vh - ${headerHeight}px)`,
|
|
|
|
|
maxHeight: `calc(100vh - ${headerHeight}px)`
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-16 22:04:12 +08:00
|
|
|
// 路由切换时滚动条滚动至顶部
|
|
|
|
|
watch(
|
|
|
|
|
() => route.fullPath,
|
|
|
|
|
() => {
|
|
|
|
|
if (!route.meta.disableScrollTo) {
|
|
|
|
|
mainScrollbarRef.value?.scrollTo(0, 0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 将滚动条的 ref provide 给子级组件
|
|
|
|
|
provide('mainScrollbarRef', mainScrollbarRef)
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2026-04-07 11:01:11 +08:00
|
|
|
.layout-container {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100vh;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
|
|
.layout-header {
|
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
background-color: var(--ma-bg-color-overlay);
|
|
|
|
|
height: 60px;
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.main-scrollbar {
|
|
|
|
|
flex: 1;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
.layout-main {
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
min-height: 100%;
|
|
|
|
|
|
|
|
|
|
.layout-content {
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-height: var(--content-min-height, 500px);
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
padding: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.layout-footer {
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
margin-top: auto;
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-16 22:04:12 +08:00
|
|
|
.user-layouts {
|
|
|
|
|
display: flex;
|
|
|
|
|
padding-top: 15px;
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
}
|
2026-04-07 11:01:11 +08:00
|
|
|
.layout-main-content {
|
2026-01-16 22:04:12 +08:00
|
|
|
padding: 0 !important;
|
|
|
|
|
overflow-x: hidden;
|
2026-04-07 11:01:11 +08:00
|
|
|
background-color: var(--ma-bg-color-overlay);
|
|
|
|
|
margin-left: 20px;
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: 768px) {
|
|
|
|
|
.layout-main-content {
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.layout-main-content-mobile {
|
|
|
|
|
padding: 0 !important;
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
background-color: var(--ma-bg-color-overlay);
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 组件样式适配 */
|
|
|
|
|
.layout-header {
|
|
|
|
|
position: fixed;
|
|
|
|
|
width: 100%;
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
|
|
|
|
|
:deep(.header-logo) {
|
|
|
|
|
span {
|
|
|
|
|
padding-left: 4px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.frontend-header-menu) {
|
|
|
|
|
background: transparent;
|
|
|
|
|
.el-menu-item,
|
|
|
|
|
.el-sub-menu .el-sub-menu__title {
|
|
|
|
|
&.is-active {
|
|
|
|
|
color: var(--el-color-primary) !important;
|
|
|
|
|
}
|
|
|
|
|
&:hover {
|
|
|
|
|
background-color: transparent !important;
|
|
|
|
|
color: var(--el-menu-hover-text-color) !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.layout-footer {
|
|
|
|
|
color: var(--el-text-color-secondary);
|
|
|
|
|
background-color: transparent !important;
|
|
|
|
|
position: relative;
|
|
|
|
|
bottom: auto;
|
|
|
|
|
width: 100%;
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 响应式断点 */
|
|
|
|
|
@media screen and (max-width: 768px) {
|
|
|
|
|
.layout-container {
|
|
|
|
|
.layout-main {
|
|
|
|
|
.layout-content {
|
|
|
|
|
--content-min-height: 300px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.user-layouts-mobile {
|
|
|
|
|
padding-top: 15px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: 1024px) {
|
|
|
|
|
.layout-container {
|
|
|
|
|
.layout-main {
|
|
|
|
|
.layout-content {
|
|
|
|
|
--content-min-height: 400px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 响应式适配 */
|
|
|
|
|
@media screen and (max-width: 1024px) {
|
|
|
|
|
.layout-container {
|
|
|
|
|
.main-scrollbar {
|
|
|
|
|
.layout-main {
|
|
|
|
|
.layout-content {
|
|
|
|
|
padding: 0 15px;
|
|
|
|
|
--content-min-height: 400px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: 768px) {
|
|
|
|
|
.layout-container {
|
|
|
|
|
.main-scrollbar {
|
|
|
|
|
.layout-main {
|
|
|
|
|
.layout-content {
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
--content-min-height: 300px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (max-height: 650px) {
|
|
|
|
|
.layout-container {
|
|
|
|
|
.main-scrollbar {
|
|
|
|
|
.layout-main {
|
|
|
|
|
.layout-content {
|
|
|
|
|
--content-min-height: 200px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-16 22:04:12 +08:00
|
|
|
}
|
|
|
|
|
</style>
|