|
|
|
@ -1,17 +1,19 @@ |
|
|
|
<script setup> |
|
|
|
// 导航栏在这 |
|
|
|
import { computed, ref } from 'vue' |
|
|
|
import { useRoute, useRouter } from 'vue-router' |
|
|
|
import { ElMessage } from 'element-plus' |
|
|
|
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"; |
|
|
|
import ChangePassword from '@/components/dialogs/changePassword.vue' |
|
|
|
import {useAdminStore} from '@/store' |
|
|
|
import {storeToRefs} from 'pinia' |
|
|
|
import {filterMenu, getRoutePath} from "@/utils/menuUtils.js"; |
|
|
|
import {Bell} from '@element-plus/icons-vue' |
|
|
|
|
|
|
|
import SettingsIcon from '@/assets/blue.png'; |
|
|
|
|
|
|
|
// 使用import.meta.glob导入所有SVG图标(修复版本) |
|
|
|
const icons = import.meta.glob('@/assets/SvgIcons/*.svg', { eager: true }) |
|
|
|
const icons = import.meta.glob('@/assets/SvgIcons/*.svg', {eager: true}) |
|
|
|
|
|
|
|
// import from '@/assets/SvgIcons/workbench.svg' |
|
|
|
// import from '@/assets/SvgIcons/activity.png' |
|
|
|
@ -51,20 +53,20 @@ const getIconPath = (menuName) => { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------- |
|
|
|
|
|
|
|
// 刷新数据功能 |
|
|
|
import API from '@/util/http.js' // 确保已经导入了HTTP请求工具 |
|
|
|
import API from '@/util/http.js' |
|
|
|
import MessageDialog from "@/components/dialogs/MessageDialog.vue"; // 确保已经导入了HTTP请求工具 |
|
|
|
|
|
|
|
// 数据刷新功能实现 |
|
|
|
const refreshData = async () => { |
|
|
|
try { |
|
|
|
// 显示加载提示,duration保持打开提示不自动关闭,showclose显示未×,点击可关闭提示 |
|
|
|
ElMessage({ message: '数据刷新中,请稍候...', type: 'info' }); |
|
|
|
ElMessage({message: '数据刷新中,请稍候...', type: 'info'}); |
|
|
|
|
|
|
|
// 调用Mysql接口获取最新数据 |
|
|
|
const response = await API({ url: '/Mysql', method: 'POST', data: {} }); |
|
|
|
const response = await API({url: '/Mysql', method: 'POST', data: {}}); |
|
|
|
if (response && response.code === 200) { |
|
|
|
|
|
|
|
const currentRoute = route.fullPath; |
|
|
|
@ -91,7 +93,7 @@ const menuList = ref([]) |
|
|
|
// 获取仓库实例 |
|
|
|
const adminStore = useAdminStore() |
|
|
|
// 解构状态(保持响应式) 获得 adminData(用户信息) 和 menuTree(菜单树) |
|
|
|
const { adminData, menuTree, flag } = storeToRefs(adminStore) |
|
|
|
const {adminData, menuTree, flag} = storeToRefs(adminStore) |
|
|
|
|
|
|
|
// 筛选权限菜单 ,menuTree 是组件通信拿的 |
|
|
|
menuList.value = filterMenu(menuTree.value) |
|
|
|
@ -151,6 +153,7 @@ const pwdRef = ref() |
|
|
|
const openChangePassword = () => { |
|
|
|
showPasswordDialog.value = true |
|
|
|
} |
|
|
|
|
|
|
|
//关闭后清空密码表单 |
|
|
|
function onPwdDialogClosed() { |
|
|
|
// 调用子组件暴露的 resetFields |
|
|
|
@ -170,9 +173,20 @@ const toggleFlag = () => { |
|
|
|
const newFlag = flag.value === 1 ? 0 : 1 |
|
|
|
adminStore.setFlag(newFlag) |
|
|
|
ElMessage.success(newFlag === 1 ? '员工数据已隐藏' : '员工数据已显示') |
|
|
|
console.log('flag',newFlag) |
|
|
|
console.log('flag', newFlag) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 消息推送逻辑 |
|
|
|
// 控制 MessageDialog 显示状态 |
|
|
|
const showMessageDialog = ref(false) |
|
|
|
|
|
|
|
// 点击铃铛图标时打开 |
|
|
|
const openMessageDialog = () => { |
|
|
|
showMessageDialog.value = true |
|
|
|
} |
|
|
|
// 消息小红点状态 |
|
|
|
const messageDot = ref(true) |
|
|
|
</script> |
|
|
|
|
|
|
|
<template> |
|
|
|
@ -183,93 +197,105 @@ const toggleFlag = () => { |
|
|
|
<div class="sidebar-container"> |
|
|
|
<el-aside class="sidebar-layout"> |
|
|
|
<div class="logo"> |
|
|
|
<img src="../assets/新logo.png" alt="logo" style="width: 9vh; height: 9vh" /> |
|
|
|
<img src="../assets/新logo.png" alt="logo" style="width: 9vh; height: 9vh"/> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="menu-scroll-container"> |
|
|
|
<el-menu :router="true" :default-active="activeMenu" style="min-height: 80vh;border:none;"> |
|
|
|
<!-- 递归渲染菜单层级 --> |
|
|
|
<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> |
|
|
|
<img |
|
|
|
:src="getIconPath(menu.menuName)" |
|
|
|
:alt="`${menu.menuName}图标`" |
|
|
|
style="width: 4vh; height: 4vh; margin-right: 4px;" |
|
|
|
> |
|
|
|
|
|
|
|
<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)"> |
|
|
|
<el-icon style="margin-right: 4px;"> |
|
|
|
<Folder /> |
|
|
|
</el-icon> |
|
|
|
<span>{{ child.menuName }}</span> |
|
|
|
</el-menu-item> |
|
|
|
|
|
|
|
<!-- 子菜单有下级 --> |
|
|
|
<el-sub-menu v-else :index="child.id.toString()"> |
|
|
|
<template #title> |
|
|
|
<el-menu :router="true" :default-active="activeMenu" style="min-height: 80vh;border:none;"> |
|
|
|
<!-- 递归渲染菜单层级 --> |
|
|
|
<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> |
|
|
|
<img |
|
|
|
:src="getIconPath(menu.menuName)" |
|
|
|
:alt="`${menu.menuName}图标`" |
|
|
|
style="width: 4vh; height: 4vh; margin-right: 4px;" |
|
|
|
> |
|
|
|
|
|
|
|
<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)"> |
|
|
|
<el-icon style="margin-right: 4px;"> |
|
|
|
<Folder /> |
|
|
|
</el-icon> |
|
|
|
<Folder/> |
|
|
|
</el-icon> |
|
|
|
<span>{{ child.menuName }}</span> |
|
|
|
</template> |
|
|
|
<!-- 递归 下一级--> |
|
|
|
<template v-for="grandChild in child.children" :key="grandChild.id"> |
|
|
|
<el-menu-item :index="getRoutePath(grandChild)"> |
|
|
|
</el-menu-item> |
|
|
|
|
|
|
|
<!-- 子菜单有下级 --> |
|
|
|
<el-sub-menu v-else :index="child.id.toString()"> |
|
|
|
<template #title> |
|
|
|
<el-icon style="margin-right: 4px;"> |
|
|
|
<Folder /> |
|
|
|
</el-icon> |
|
|
|
<span>{{ grandChild.menuName }}</span> |
|
|
|
</el-menu-item> |
|
|
|
</template> |
|
|
|
</el-sub-menu> |
|
|
|
</template> |
|
|
|
</el-sub-menu> |
|
|
|
|
|
|
|
<!-- 无子菜单的一级菜单 --> |
|
|
|
<el-menu-item v-else :index="getRoutePath(menu)"> |
|
|
|
<img |
|
|
|
:src="getIconPath(menu.menuName)" |
|
|
|
:alt="`${menu.menuName}图标`" |
|
|
|
style="width: 4vh; height: 4vh; margin-right: 4px;" |
|
|
|
> |
|
|
|
<span>{{ menu.menuName }}</span> |
|
|
|
</el-menu-item> |
|
|
|
</template> |
|
|
|
</el-menu> |
|
|
|
<Folder/> |
|
|
|
</el-icon> |
|
|
|
<span>{{ child.menuName }}</span> |
|
|
|
</template> |
|
|
|
<!-- 递归 下一级--> |
|
|
|
<template v-for="grandChild in child.children" :key="grandChild.id"> |
|
|
|
<el-menu-item :index="getRoutePath(grandChild)"> |
|
|
|
<el-icon style="margin-right: 4px;"> |
|
|
|
<Folder/> |
|
|
|
</el-icon> |
|
|
|
<span>{{ grandChild.menuName }}</span> |
|
|
|
</el-menu-item> |
|
|
|
</template> |
|
|
|
</el-sub-menu> |
|
|
|
</template> |
|
|
|
</el-sub-menu> |
|
|
|
|
|
|
|
<!-- 无子菜单的一级菜单 --> |
|
|
|
<el-menu-item v-else :index="getRoutePath(menu)"> |
|
|
|
<img |
|
|
|
:src="getIconPath(menu.menuName)" |
|
|
|
:alt="`${menu.menuName}图标`" |
|
|
|
style="width: 4vh; height: 4vh; margin-right: 4px;" |
|
|
|
> |
|
|
|
<span>{{ menu.menuName }}</span> |
|
|
|
</el-menu-item> |
|
|
|
</template> |
|
|
|
</el-menu> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 底部固定的设置中心 --> |
|
|
|
<div class="settings-container"> |
|
|
|
<el-dropdown placement="top-start"> |
|
|
|
<div style="display: flex"> |
|
|
|
<!-- 底部固定的设置中心 --> |
|
|
|
<div class="settings-container"> |
|
|
|
<el-dropdown placement="top-start"> |
|
|
|
<span class="el-dropdown-link"> |
|
|
|
<!-- 暂时使用静态路径,确保设置图标正常显示 --> |
|
|
|
<img src="@/assets/SvgIcons/设置.svg" alt="设置" style="width: 4vh; height: 4vh" /> |
|
|
|
<img src="@/assets/SvgIcons/设置.svg" alt="设置" style="width: 4vh; height: 4vh"/> |
|
|
|
<span>设置中心</span> |
|
|
|
<el-icon class="arrow-icon"> |
|
|
|
<ArrowUp /> |
|
|
|
<ArrowUp/> |
|
|
|
</el-icon> |
|
|
|
</span> |
|
|
|
<template #dropdown> |
|
|
|
<el-dropdown-menu> |
|
|
|
<el-dropdown-item @click="refreshData()">数据刷新</el-dropdown-item> |
|
|
|
<!-- 员工数据开关 --> |
|
|
|
<el-dropdown-item @click="toggleFlag()"> |
|
|
|
{{ flag === 1 ? '显示员工数据' : '隐藏员工数据' }} |
|
|
|
</el-dropdown-item> |
|
|
|
<el-dropdown-item @click="message()">查看个人信息</el-dropdown-item> |
|
|
|
<el-dropdown-item @click="openChangePassword">修改密码</el-dropdown-item> |
|
|
|
<el-dropdown-item @click="logout">退出登录</el-dropdown-item> |
|
|
|
</el-dropdown-menu> |
|
|
|
</template> |
|
|
|
</el-dropdown> |
|
|
|
<template #dropdown> |
|
|
|
<el-dropdown-menu> |
|
|
|
<el-dropdown-item @click="refreshData()">数据刷新</el-dropdown-item> |
|
|
|
<!-- 员工数据开关 --> |
|
|
|
<el-dropdown-item @click="toggleFlag()"> |
|
|
|
{{ flag === 1 ? '显示员工数据' : '隐藏员工数据' }} |
|
|
|
</el-dropdown-item> |
|
|
|
<el-dropdown-item @click="message()">查看个人信息</el-dropdown-item> |
|
|
|
<el-dropdown-item @click="openChangePassword">修改密码</el-dropdown-item> |
|
|
|
<el-dropdown-item @click="logout">退出登录</el-dropdown-item> |
|
|
|
</el-dropdown-menu> |
|
|
|
</template> |
|
|
|
</el-dropdown> |
|
|
|
</div> |
|
|
|
<!-- 消息提示 --> |
|
|
|
<div class="message-container"> |
|
|
|
<el-badge :is-dot="messageDot" class="item"> |
|
|
|
<el-icon @click="openMessageDialog" style="cursor: pointer;"> |
|
|
|
<Bell/> |
|
|
|
</el-icon> |
|
|
|
</el-badge> |
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</el-aside> |
|
|
|
</div> |
|
|
|
|
|
|
|
@ -314,8 +340,17 @@ const toggleFlag = () => { |
|
|
|
|
|
|
|
<!-- 自定义密码修改弹窗组件 --> |
|
|
|
<el-dialog v-model="showPasswordDialog" :center="true" width="470px" @closed="onPwdDialogClosed"> |
|
|
|
<ChangePassword ref="pwdRef" @confirm="showPasswordDialog = false" /> |
|
|
|
<ChangePassword ref="pwdRef" @confirm="showPasswordDialog = false"/> |
|
|
|
</el-dialog> |
|
|
|
|
|
|
|
<MessageDialog |
|
|
|
v-if="showMessageDialog" |
|
|
|
@close="showMessageDialog = false" |
|
|
|
@update-dot="messageDot = $event" |
|
|
|
/> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -355,6 +390,7 @@ const toggleFlag = () => { |
|
|
|
flex-shrink: 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
.logo { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
@ -362,6 +398,7 @@ const toggleFlag = () => { |
|
|
|
height: 12vh; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* 中间可滚动菜单容器 */ |
|
|
|
.menu-scroll-container { |
|
|
|
flex: 1; |
|
|
|
@ -376,6 +413,12 @@ const toggleFlag = () => { |
|
|
|
align-items: center; /* 垂直居中 */ |
|
|
|
} |
|
|
|
|
|
|
|
.message-container { |
|
|
|
padding: 10px 50px 10px 50px; /* 上,右, 下,左 */ |
|
|
|
display: flex; |
|
|
|
align-items: center; /* 垂直居中 */ |
|
|
|
} |
|
|
|
|
|
|
|
/* 调整下拉菜单的样式,确保它向上弹出 */ |
|
|
|
|
|
|
|
.el-dropdown-link:focus { |
|
|
|
@ -383,12 +426,14 @@ const toggleFlag = () => { |
|
|
|
outline: none; |
|
|
|
text-decoration: none; |
|
|
|
} |
|
|
|
|
|
|
|
.el-dropdown-link { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
cursor: pointer; |
|
|
|
gap:10px; /* 图标和文字左右间距 */ |
|
|
|
gap: 10px; /* 图标和文字左右间距 */ |
|
|
|
} |
|
|
|
|
|
|
|
.sidebar-layout { |
|
|
|
width: 15vw; |
|
|
|
height: 100%; |
|
|
|
@ -439,7 +484,6 @@ const toggleFlag = () => { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 确保el-menu撑满容器 */ |
|
|
|
.sidebar-layout .el-menu { |
|
|
|
width: 100%; |
|
|
|
@ -456,6 +500,7 @@ const toggleFlag = () => { |
|
|
|
::v-deep(.el-menu-item:hover) { |
|
|
|
background: #E5EBFE; |
|
|
|
} |
|
|
|
|
|
|
|
/* 子菜单展开时和背景同色 */ |
|
|
|
::v-deep(.el-sub-menu__title), |
|
|
|
::v-deep(.el-menu-item) { |
|
|
|
@ -470,7 +515,6 @@ const toggleFlag = () => { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 确保全局el-container适应容器 */ |
|
|
|
:deep(.el-container) { |
|
|
|
/* vue3的深度选择器,用于覆盖element-plus的默认样式 */ |
|
|
|
@ -480,7 +524,6 @@ const toggleFlag = () => { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 为侧边栏和主内容区域添加滚动条样式 */ |
|
|
|
.menu-scroll-container, |
|
|
|
.el-main { |
|
|
|
|