Files
effekt-interface-frontend/src/components/Home.vue
2026-04-22 10:40:32 +08:00

235 lines
7.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="auto-test-main" style="height: 100%">
<el-container style="height: 100%">
<div class="aside" style="height: 100%">
<el-menu
:default-active="$route.path"
class="el-menu-vertical-demo"
:collapse="isCollapse"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
:router="true">
<template v-for="menu in displayMenus">
<el-submenu v-if="menu.children && menu.children.length > 0" :index="menuIndex(menu)" :key="'sub-' + menuKey(menu)">
<template slot="title">
<i :class="menuIcon(menu)"></i>
<span slot="title">{{ menu.name }}</span>
</template>
<template v-for="child in menu.children">
<!-- 处理可能有第三级菜单的情况 -->
<el-submenu v-if="child.children && child.children.length > 0" :index="menuIndex(child)" :key="'child-sub-' + menuKey(child)">
<template slot="title">
<i v-if="child.icon" :class="menuIcon(child)"></i>
<span slot="title">{{ child.name }}</span>
</template>
<el-menu-item v-for="subChild in child.children" :index="menuPath(subChild)" :key="'subchild-item-' + menuKey(subChild)">
<i v-if="subChild.icon" :class="menuIcon(subChild)"></i>
<span slot="title">{{ subChild.name }}</span>
</el-menu-item>
</el-submenu>
<!-- 只有两级菜单 -->
<el-menu-item v-else :index="menuPath(child)" :key="'child-item-' + menuKey(child)">
<i v-if="child.icon" :class="menuIcon(child)"></i>
<span slot="title">{{ child.name }}</span>
</el-menu-item>
</template>
</el-submenu>
<el-menu-item v-else :index="menuPath(menu)" :key="'item-' + menuKey(menu)">
<i :class="menuIcon(menu)"></i>
<span slot="title">{{ menu.name }}</span>
</el-menu-item>
</template>
</el-menu>
</div>
<el-container>
<el-header class="header" style="background-color: rgba(230, 226, 215, 0.9)">
<div class="header-left">
<div class="header-icon">
<i v-if="isCollapse" class="el-icon-s-unfold" style="font-size: 20px" @click="setCollapse"></i>
<i v-else class="el-icon-s-fold" style="font-size: 20px" @click="setCollapse"></i>
</div>
<div class="system-name">
<span>{{ systemName }}</span>
</div>
</div>
<div class="header-user">
<el-dropdown v-if="currentUser" trigger="click" @command="handleUserCommand">
<span class="user-name-dropdown">
{{ displayName }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span v-else class="login-label" @click="goLogin">登录</span>
</div>
</el-header>
<el-main>
<router-view class="main-form" name="Manage"></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return {
isCollapse: false,
systemName: '效能平台'
}
},
computed: {
currentUser() {
return this.$store.state.currentUser
},
userMenus() {
return this.$store.state.userMenus || []
},
displayMenus() {
if (!this.userMenus.length) {
return [{ name: '首页', path: '/effekt', icon: 'el-icon-house', children: [] }]
}
return this.filterMenus(this.userMenus)
},
displayName() {
if (!this.currentUser) {
return ''
}
return this.currentUser.username || this.currentUser.realName || '未命名用户'
}
},
methods: {
setCollapse() {
this.isCollapse = !this.isCollapse
},
goLogin() {
this.$router.push({ name: 'login' })
},
menuKey(item) {
return String(item.menuId || item.id || item.path || item.name)
},
menuIndex(item) {
return String(item.path || item.code || item.menuId || item.id || item.name)
},
menuPath(item) {
const pathMap = {
'/system/role': '/system/roles',
'/system/user': '/system/users',
'/system/menu': '/system/menus'
}
return pathMap[item.path] || item.path || '/effekt'
},
menuIcon(item) {
// 按照原来的静态菜单名称映射图标
const nameIconMap = {
'首页': 'el-icon-house',
'测试协作工作台': 'el-icon-s-operation',
'测试平台': 'el-icon-s-platform',
'产品管理': 'el-icon-box',
'项目管理': 'el-icon-s-management',
'用例管理': 'el-icon-document',
'测试计划': 'el-icon-date',
'测试报告': 'el-icon-data-line',
'测试工具': 'el-icon-s-tools',
'造数工具': 'el-icon-magic-stick',
'数据库造数': 'el-icon-coin',
'造数工厂': 'el-icon-set-up',
'系统管理': 'el-icon-setting',
'角色管理': 'el-icon-user-solid',
'用户管理': 'el-icon-user',
'权限管理': 'el-icon-lock',
'菜单管理': 'el-icon-menu'
}
const iconMap = {
setting: 'el-icon-setting',
peoples: 'el-icon-user-solid',
user: 'el-icon-user',
lock: 'el-icon-lock',
menu: 'el-icon-menu'
}
// 优先级:先匹配名称,再匹配接口中指定的 icon最后返回默认图标 el-icon-menu
if (item.name && nameIconMap[item.name]) {
return nameIconMap[item.name]
}
return iconMap[item.icon] || (item.icon && item.icon.indexOf('el-icon-') === 0 ? item.icon : 'el-icon-menu')
},
filterMenus(menus) {
return (menus || []).filter(item => item.visible !== 0 && item.status !== 0).map(item => {
const children = this.filterMenus(item.children || [])
return Object.assign({}, item, { children })
}).filter(item => {
if (item.children && item.children.length) {
return true
}
return !!item.path && !!this.menuPath(item)
})
},
handleUserCommand(command) {
if (command === 'logout') {
localStorage.removeItem('authUser')
localStorage.removeItem('accessToken')
localStorage.removeItem('userMenus')
this.$store.commit('ClearCurrentUser')
this.$message.success('已退出登录')
this.$router.push({ name: 'login' })
}
}
}
}
</script>
<style scoped>
.auto-test-main {
height: 100%;
padding: 0;
margin: 0;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
/*min-height: 400px;*/
}
.header {
height: 60px;
line-height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
}
.el-header {
padding: 0 20px 0 0;
}
.el-menu-vertical-demo {
height: 100%;
}
.header-left {
display: flex;
align-items: center;
}
.header-icon {
padding-left: 15px;
padding-right: 15px;
}
.header-user {
color: #333;
font-size: 14px;
}
.login-label {
color: #409EFF;
cursor: pointer;
}
</style>