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.
haoliang-net/frontend/src/layouts/AdminLayout.vue

236 lines
6.4 KiB
Vue

<template>
<div class="admin-layout">
<!-- 顶部栏 -->
<header class="admin-header">
<div class="header-left">
<span class="system-title">CNC机床数据采集系统</span>
</div>
<div class="header-right">
<el-dropdown trigger="click" @command="handleCommand">
<span class="admin-dropdown">
管理员 <el-icon><ArrowDown /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="password">修改密码</el-dropdown-item>
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</header>
<div class="admin-body">
<!-- 侧边栏 -->
<aside class="admin-sidebar" :class="{ collapsed: isCollapsed }">
<el-menu
:default-active="currentRoute"
:collapse="isCollapsed"
background-color="#304156"
text-color="#bfcbd9"
active-text-color="#409EFF"
router
>
<el-menu-item :index="menuPath('/dashboard')">
<el-icon><Odometer /></el-icon>
<template #title>仪表盘</template>
</el-menu-item>
<el-menu-item :index="menuPath('/machine')">
<el-icon><Monitor /></el-icon>
<template #title>设备管理</template>
</el-menu-item>
<el-menu-item :index="menuPath('/brand')">
<el-icon><PriceTag /></el-icon>
<template #title>品牌模板</template>
</el-menu-item>
<el-menu-item :index="menuPath('/collect-address')">
<el-icon><Link /></el-icon>
<template #title>采集地址</template>
</el-menu-item>
<el-menu-item :index="menuPath('/collect-log')">
<el-icon><Notebook /></el-icon>
<template #title>采集日志</template>
</el-menu-item>
<el-menu-item :index="menuPath('/worker')">
<el-icon><User /></el-icon>
<template #title>员工管理</template>
</el-menu-item>
<el-menu-item :index="menuPath('/production')">
<el-icon><DataAnalysis /></el-icon>
<template #title>产量报表</template>
</el-menu-item>
<el-menu-item :index="menuPath('/alert')">
<el-icon><Bell /></el-icon>
<template #title>告警中心</template>
</el-menu-item>
<el-menu-item :index="menuPath('/settings')">
<el-icon><Setting /></el-icon>
<template #title>系统设置</template>
</el-menu-item>
<el-menu-item :index="menuPath('/log')">
<el-icon><Document /></el-icon>
<template #title>操作日志</template>
</el-menu-item>
<el-menu-item :index="menuPath('/simulator')">
<el-icon><VideoPlay /></el-icon>
<template #title>模拟采集</template>
</el-menu-item>
<el-menu-item :index="menuPath('/screen-config')">
<el-icon><FullScreen /></el-icon>
<template #title>大屏配置</template>
</el-menu-item>
</el-menu>
<div class="sidebar-toggle" @click="isCollapsed = !isCollapsed">
<el-icon v-if="isCollapsed"><Expand /></el-icon>
<el-icon v-else><Fold /></el-icon>
</div>
</aside>
<!-- 内容区 -->
<main class="admin-content">
<div class="breadcrumb-area">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: isMock ? '/mock/dashboard' : '/dashboard' }">首页</el-breadcrumb-item>
<el-breadcrumb-item v-if="route.meta.title && route.name !== 'Dashboard' && route.name !== 'MockDashboard'">
{{ route.meta.title }}
</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="content-area">
<router-view />
</div>
</main>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessageBox, ElMessage } from 'element-plus'
import { ArrowDown, Notebook } from '@element-plus/icons-vue'
import { useMockMode } from '@/composables/useMockMode'
const route = useRoute()
const router = useRouter()
const { isMock } = useMockMode()
const isCollapsed = ref(false)
// 根据当前模式生成菜单路径
function menuPath(path: string): string {
return isMock.value ? `/mock${path}` : path
}
const currentRoute = computed(() => route.path)
function handleCommand(command: string) {
if (command === 'password') {
router.push(isMock.value ? '/mock/settings' : '/settings')
} else if (command === 'logout') {
ElMessageBox.confirm('确定退出登录?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
localStorage.removeItem('token')
router.push(isMock.value ? '/mock/login' : '/login')
ElMessage.success('已退出登录')
}).catch(() => {})
}
}
</script>
<style scoped lang="scss">
.admin-layout {
height: 100vh;
display: flex;
flex-direction: column;
}
.admin-header {
height: 48px;
background-color: #409EFF;
color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
flex-shrink: 0;
.header-left {
.system-title {
font-size: 16px;
font-weight: bold;
}
}
.header-right {
.admin-dropdown {
color: #fff;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
}
}
}
.admin-body {
flex: 1;
display: flex;
overflow: hidden;
}
.admin-sidebar {
width: 200px;
background-color: #304156;
display: flex;
flex-direction: column;
transition: width 0.3s;
flex-shrink: 0;
&.collapsed {
width: 64px;
}
.el-menu {
flex: 1;
border-right: none;
overflow-y: auto;
}
.sidebar-toggle {
height: 40px;
display: flex;
align-items: center;
justify-content: center;
color: #bfcbd9;
cursor: pointer;
border-top: 1px solid #263445;
&:hover {
color: #409EFF;
}
}
}
.admin-content {
flex: 1;
display: flex;
flex-direction: column;
background-color: #f0f2f5;
overflow: hidden;
.breadcrumb-area {
padding: 12px 20px 0;
flex-shrink: 0;
}
.content-area {
flex: 1;
padding: 20px;
overflow-y: auto;
}
}
</style>