Data_Analysis/analytics-demo-web/src/layouts/AppLayout.vue

132 lines
3.1 KiB
Vue

<script setup lang="ts">
import { SwitchButton } from '@element-plus/icons-vue'
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { menuSections } from '../config/menu'
import { useAuthStore } from '../stores/useAuth'
const route = useRoute()
const router = useRouter()
const auth = useAuthStore()
function logout() {
auth.logout()
router.push({ path: '/login' })
}
const activePath = computed(() => route.path)
function onSelect(path: string) {
router.push(path)
}
const breadcrumbItems = computed(() => {
for (const section of menuSections) {
for (const group of section.children) {
const leaf = group.children.find((item) => item.path === route.path)
if (leaf) {
return [section.title, group.title, leaf.title]
}
}
}
return ['首页']
})
</script>
<template>
<el-container class="app-shell">
<el-aside width="280px" class="side">
<div class="brand">贝朗医疗数据分析 Demo</div>
<el-menu :default-active="activePath" class="menu" @select="onSelect">
<el-sub-menu v-for="section in menuSections" :key="section.title" :index="section.basePath">
<template #title>{{ section.title }}</template>
<el-sub-menu
v-for="group in section.children"
:key="`${section.title}-${group.title}`"
:index="`${section.basePath}-${group.title}`"
>
<template #title>{{ group.title }}</template>
<el-menu-item v-for="leaf in group.children" :key="leaf.path" :index="leaf.path">
{{ leaf.title }}
</el-menu-item>
</el-sub-menu>
</el-sub-menu>
</el-menu>
</el-aside>
<el-container>
<el-header class="header">
<el-breadcrumb separator="/" class="header-crumb">
<el-breadcrumb-item v-for="item in breadcrumbItems" :key="item">{{ item }}</el-breadcrumb-item>
</el-breadcrumb>
<div class="header-actions">
<span class="user-label">Demo</span>
<el-button type="primary" link @click="logout">
<el-icon class="el-icon--left"><SwitchButton /></el-icon>
退出登录
</el-button>
</div>
</el-header>
<el-main class="main">
<router-view />
</el-main>
</el-container>
</el-container>
</template>
<style scoped>
.app-shell {
min-height: 100vh;
background: var(--bg-color, #f5f7fa);
}
.side {
background: #001529;
color: #fff;
border-right: 1px solid var(--border-color, #e5e7eb);
}
.brand {
padding: 18px 16px;
font-size: 16px;
font-weight: 600;
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}
.menu {
border-right: none;
background: transparent;
}
.header {
background: #fff;
border-bottom: 1px solid var(--border-color, #eef2f6);
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 0 16px;
}
.header-crumb {
flex: 1;
min-width: 0;
}
.header-actions {
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
}
.user-label {
font-size: 13px;
color: var(--el-text-color-secondary);
}
.main {
padding: 16px;
}
</style>