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.
236 lines
6.4 KiB
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>
|