You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
7.4 KiB
Vue
280 lines
7.4 KiB
Vue
<template>
|
|
<el-container class="layout-container">
|
|
<el-aside :width="isCollapsed ? '64px' : '200px'" class="aside">
|
|
<div class="logo">
|
|
<svg t="1776756485739" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2128" width="32" height="32"><path d="M512 40.832a381.76 381.76 0 1 0 381.76 381.76A381.824 381.824 0 0 0 512 40.832zM307.2 206.208a44.8 44.8 0 1 1 44.8 44.8 44.8 44.8 0 0 1-44.8-44.8zM512 582.272a159.68 159.68 0 1 1 159.68-159.68A159.68 159.68 0 0 1 512 582.272z m0 0" fill="#409EFF" p-id="2129"></path><path d="M797.312 761.728a380.416 380.416 0 0 1-567.104 4.16l-70.4 161.216c-12.8 30.016 12.8 56.128 57.6 56.128h593.984c45.312 0 70.976-26.112 57.6-56.128z m0 0" fill="#409EFF" p-id="2130"></path></svg>
|
|
<span v-if="!isCollapsed">视觉管理</span>
|
|
</div>
|
|
|
|
<el-menu
|
|
:default-active="activeMenu"
|
|
:collapse="isCollapsed"
|
|
:collapse-transition="false"
|
|
router
|
|
class="menu"
|
|
>
|
|
<el-menu-item index="/home">
|
|
<el-icon><HomeFilled /></el-icon>
|
|
<template #title>首页</template>
|
|
</el-menu-item>
|
|
<el-menu-item index="/dataset">
|
|
<el-icon><FolderOpened /></el-icon>
|
|
<template #title>数据集</template>
|
|
</el-menu-item>
|
|
<el-menu-item index="/face-recognition">
|
|
<el-icon><UserFilled /></el-icon>
|
|
<template #title>人脸识别</template>
|
|
</el-menu-item>
|
|
<el-menu-item index="/personnel">
|
|
<el-icon><Avatar /></el-icon>
|
|
<template #title>人员管理</template>
|
|
</el-menu-item>
|
|
<el-menu-item index="/smart-tracking">
|
|
<el-icon><Aim /></el-icon>
|
|
<template #title>智能追踪</template>
|
|
</el-menu-item>
|
|
</el-menu>
|
|
</el-aside>
|
|
|
|
<el-container>
|
|
<el-header class="header">
|
|
<div class="header-left">
|
|
<el-icon class="collapse-btn" @click="isCollapsed = !isCollapsed">
|
|
<Fold v-if="!isCollapsed" />
|
|
<Expand v-else />
|
|
</el-icon>
|
|
</div>
|
|
|
|
<div class="header-right">
|
|
<!-- <el-popover
|
|
placement="bottom"
|
|
:width="300"
|
|
trigger="click"
|
|
>
|
|
<template #reference>
|
|
<el-icon class="header-icon"><Brush /></el-icon>
|
|
</template>
|
|
<div class="theme-picker">
|
|
<h4>切换主题颜色</h4>
|
|
<div class="color-list">
|
|
<div
|
|
v-for="item in themeStore.themeColors"
|
|
:key="item.color"
|
|
class="color-item"
|
|
:style="{ backgroundColor: item.color }"
|
|
:class="{ active: item.color === themeStore.themeColor }"
|
|
@click="handleChangeTheme(item.color)"
|
|
>
|
|
<el-icon v-if="item.color === themeStore.themeColor"><Check /></el-icon>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</el-popover> -->
|
|
|
|
<el-dropdown @command="handleCommand">
|
|
<span class="user-info">
|
|
<el-avatar :size="32" icon="UserFilled" />
|
|
<span class="username">{{ userStore.userInfo?.userName || '用户' }}</span>
|
|
<el-icon><ArrowDown /></el-icon>
|
|
</span>
|
|
<template #dropdown>
|
|
<el-dropdown-menu>
|
|
<el-dropdown-item command="profile">
|
|
<el-icon><User /></el-icon>个人中心
|
|
</el-dropdown-item>
|
|
<el-dropdown-item command="settings">
|
|
<el-icon><Setting /></el-icon>设置
|
|
</el-dropdown-item>
|
|
<el-dropdown-item divided command="logout">
|
|
<el-icon><SwitchButton /></el-icon>退出登录
|
|
</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</template>
|
|
</el-dropdown>
|
|
</div>
|
|
</el-header>
|
|
|
|
<el-main class="main">
|
|
<router-view />
|
|
</el-main>
|
|
</el-container>
|
|
</el-container>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
|
import { useUserStore } from '@/stores/user'
|
|
import { useThemeStore } from '@/stores/theme'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const userStore = useUserStore()
|
|
const themeStore = useThemeStore()
|
|
|
|
const isCollapsed = ref(false)
|
|
const activeMenu = computed(() => route.path)
|
|
|
|
const handleChangeTheme = (color) => {
|
|
themeStore.setThemeColor(color)
|
|
ElMessage.success('主题颜色已切换')
|
|
}
|
|
|
|
const handleCommand = (command) => {
|
|
switch (command) {
|
|
case 'logout':
|
|
ElMessageBox.confirm('确定要退出登录吗?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
userStore.logout()
|
|
router.push('/login')
|
|
ElMessage.success('已退出登录')
|
|
}).catch(() => {})
|
|
break
|
|
case 'profile':
|
|
ElMessage.info('个人中心功能开发中')
|
|
break
|
|
case 'settings':
|
|
ElMessage.info('设置功能开发中')
|
|
break
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@use '@/styles/variables.scss' as *;
|
|
@use '@/styles/mixin.scss' as *;
|
|
|
|
.layout-container {
|
|
height: 100vh;
|
|
}
|
|
|
|
.aside {
|
|
background: #fff;
|
|
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.05);
|
|
transition: width 0.3s;
|
|
overflow: hidden;
|
|
|
|
.logo {
|
|
height: 60px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
color: var(--el-color-primary);
|
|
border-bottom: 1px solid $border-light;
|
|
|
|
img {
|
|
width: 32px;
|
|
height: 32px;
|
|
}
|
|
}
|
|
|
|
.menu {
|
|
border-right: none;
|
|
}
|
|
}
|
|
|
|
.header {
|
|
background: #fff;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 20px;
|
|
|
|
.header-left {
|
|
.collapse-btn {
|
|
font-size: 20px;
|
|
cursor: pointer;
|
|
color: $text-regular;
|
|
transition: color 0.3s;
|
|
|
|
&:hover {
|
|
color: $primary-color;
|
|
}
|
|
}
|
|
}
|
|
|
|
.header-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
|
|
.header-icon {
|
|
font-size: 20px;
|
|
cursor: pointer;
|
|
color: $text-regular;
|
|
transition: color 0.3s;
|
|
|
|
&:hover {
|
|
color: $primary-color;
|
|
}
|
|
}
|
|
|
|
.user-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
|
|
.username {
|
|
font-size: 14px;
|
|
color: $text-regular;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.main {
|
|
background: $bg-base;
|
|
padding: 20px;
|
|
}
|
|
|
|
.theme-picker {
|
|
h4 {
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
margin-bottom: 15px;
|
|
color: $text-primary;
|
|
}
|
|
|
|
.color-list {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 12px;
|
|
|
|
.color-item {
|
|
width: 50px;
|
|
height: 50px;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #fff;
|
|
transition: all 0.3s;
|
|
border: 2px solid transparent;
|
|
|
|
&:hover {
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
&.active {
|
|
border-color: $text-primary;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
:deep(.el-menu--collapse .el-menu-item span) {
|
|
display: none;
|
|
}
|
|
</style>
|