You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

281 lines
8.1 KiB

<script setup>
// 导航栏在这
import {computed, ref} from 'vue'
import {useRoute, useRouter} from 'vue-router'
import {ElMessage} from 'element-plus'
import dmmn from '../assets/link.png'
import ChangePassword from '@/components/changePassword.vue'
import {useAdminStore} from '@/store'
import {storeToRefs} from 'pinia'
import {filterMenu, getRoutePath} from "@/utils/menuUtils.js";
// 存储接口返回的菜单数据
const menuList = ref([])
// 获取仓库实例
const adminStore = useAdminStore()
// 解构状态(保持响应式) 获得 adminData(用户信息) 和 menuTree(菜单树)
const {adminData, menuTree} = storeToRefs(adminStore)
// 筛选权限菜单 ,menuTree 是组件通信拿的
menuList.value = filterMenu(menuTree.value)
console.log("menuList", menuList.value)
// 获取当前路由
const route = useRoute()
// 通用函数:从菜单树中递归找出最匹配的 index
function findBestMatch(menuList, path) {
let bestMatch = ''
function traverse(menus) {
for (const item of menus) {
const itemPath = getRoutePath(item)
// 如果当前菜单的 path 是当前路径的前缀,可能是候选项
if (path.startsWith(itemPath) && itemPath.length > bestMatch.length) {
bestMatch = itemPath
}
if (item.children && item.children.length > 0) {
traverse(item.children)
}
}
}
traverse(menuList)
return bestMatch || path // fallback 到当前路径
}
// 响应式高亮菜单
const activeMenu = computed(() => {
return findBestMatch(menuList.value, route.path)
})
const router = useRouter()
const imgrule1 = dmmn
const messageVisible = ref(false)
// 查看个人信息弹出框
const openMessage = function () {
messageVisible.value = true
}
// 关闭个人信息
const closeMessage = function () {
messageVisible.value = false
}
const message = function () {
openMessage()
}
// 显示修改密码弹窗
const showPasswordDialog = ref(false)
//打开修改密码弹窗
const openChangePassword = () => {
showPasswordDialog.value = true
}
function logout() {
const machineId = localStorage.getItem('machineId')
localStorage.removeItem('token')
adminStore.clearState()
router.push('/login?machineId=' + machineId)
ElMessage.success('退出成功')
}
</script>
<template>
<div class="common-layout">
<el-container>
<el-aside style="
width: 15%;
min-width: 180px;
position: fixed; /* 固定位置 */
top: 0;
left: 0;
height: 100vh; /* 高度占满视口 */
z-index: 100; /* 确保侧边栏在其他元素之上 */
">
<div class="logo">
<img src="../assets/新logo.png" alt="logo" style="width: 80px; height: 80px"/>
<!-- <div style="font-size: 16px; font-weight: bold; color: black; text-align: center;" ><h1>海外金币管理系统</h1></div> -->
</div>
<el-card style="min-height: 90%;">
<el-menu
:router="true"
class="el-menu-vertical-demo"
:default-active="activeMenu"
>
<!-- 递归渲染菜单层级 -->
<template v-for="menu in menuList" :key="menu.id">
<!-- 有子菜单的父级菜单(menuType=2 且存在children) -->
<el-sub-menu
v-if="menu.children && menu.children.length > 0"
:index="menu.id.toString()"
>
<template #title>
<el-icon>
<Folder/>
</el-icon>
<span>{{ menu.menuName }}</span>
</template>
<!-- 子菜单 -->
<template v-for="child in menu.children" :key="child.id">
<!-- 子菜单为叶子节点(无children) -->
<el-menu-item
v-if="!child.children || child.children.length === 0"
:index="getRoutePath(child)"
>
<span>{{ child.menuName }}</span>
</el-menu-item>
<!-- 子菜单有下级 -->
<el-sub-menu
v-else
:index="child.id.toString()"
>
<template #title>
<span>{{ child.menuName }}</span>
</template>
<!-- 递归 下一级-->
<template v-for="grandChild in child.children" :key="grandChild.id">
<el-menu-item :index="getRoutePath(grandChild)">
<span>{{ grandChild.menuName }}</span>
</el-menu-item>
</template>
</el-sub-menu>
</template>
</el-sub-menu>
<!-- 无子菜单的一级菜单 -->
<el-menu-item
v-else
:index="getRoutePath(menu)"
>
<el-icon>
<Folder/>
</el-icon>
<span>{{ menu.menuName }}</span>
</el-menu-item>
</template>
</el-menu>
</el-card>
</el-aside>
<el-container style="margin-left: 15%; min-width: 180px">
<!-- 修改 el-header 样式 -->
<el-header style="
position: fixed;
top: 0;
left: 15%;
right: 0;
z-index: 80;
background: white;
">
<el-menu class="el-menu-demo" mode="horizontal" :ellipsis="false">
<el-sub-menu index="1" class="admin">
<template #title>
<el-image :src="imgrule1" alt="错误" style="width: 50px; height: 50px"/>
<span style="margin-left: 10px">{{ adminData.name }}</span>
</template>
<el-menu-item @click="message()">查看个人信息</el-menu-item>
<el-menu-item @click="openChangePassword">修改密码</el-menu-item>
<el-menu-item @click="logout">退出登录</el-menu-item>
</el-sub-menu>
</el-menu>
</el-header>
<el-main style="margin-top: 60px">
<!-- 60px 是 el-header 的大致高度,可根据实际情况调整 -->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
<!-- 查看个人信息 -->
<el-dialog v-model="messageVisible" title="查看个人信息" width="500px">
<el-form :model="adminData">
<el-form-item label="用户姓名" label-width="100px" label-position="left">
<span class="message-font">{{ adminData.adminName }}</span>
</el-form-item>
<el-form-item label="精网号" label-width="100px" label-position="left">
<span class="message-font">{{ adminData.account }}</span>
</el-form-item>
<el-form-item label="地区" label-width="100px" label-position="left">
<span class="message-font">{{ adminData.markets }}</span>
</el-form-item>
<el-form-item label="注册时间" label-width="100px" label-position="left">
<span class="message-font">{{ adminData.createTime }}</span>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button text @click="closeMessage()">关闭</el-button>
</div>
</template>
</el-dialog>
<!-- 自定义密码修改弹窗组件 -->
<el-dialog
v-model="showPasswordDialog"
:center="true"
width="470px"
>
<ChangePassword @confirm="showPasswordDialog = false"/>
</el-dialog>
</div>
</template>
<style scoped>
.message-font {
font-size: 16px;
font-weight: bold;
}
.item {
margin-top: 20px;
margin-right: 40px;
}
.admin {
margin-left: auto;
}
.el-aside {
min-height: 100vh;
width: 200px;
}
/* background-color: #BFD8D2; */
.logo {
margin: 20px 0px 20px 20px;
display: flex;
}
.el-menu-demo {
border: none;
/* 去除边框 */
padding: 0;
/* 去除内边距 */
float: right;
/* 将菜单向右浮动 */
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 240px;
min-height: 400px;
border: none;
/* 去除边框 */
}
</style>