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.

290 lines
8.3 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <script setup>
  2. // 导航栏在这
  3. import {computed, ref} from 'vue'
  4. import {useRoute, useRouter} from 'vue-router'
  5. import {ElMessage} from 'element-plus'
  6. import dmmn from '../assets/link.png'
  7. import ChangePassword from '@/components/changePassword.vue'
  8. import {useAdminStore} from '@/store'
  9. import {storeToRefs} from 'pinia'
  10. import {filterMenu, getRoutePath} from "@/utils/menuUtils.js";
  11. // 存储接口返回的菜单数据
  12. const menuList = ref([])
  13. // 获取仓库实例
  14. const adminStore = useAdminStore()
  15. // 解构状态(保持响应式) 获得 adminData(用户信息) 和 menuTree(菜单树)
  16. const {adminData, menuTree} = storeToRefs(adminStore)
  17. // 筛选权限菜单 ,menuTree 是组件通信拿的
  18. menuList.value = filterMenu(menuTree.value)
  19. console.log("menuList", menuList.value)
  20. // 获取当前路由
  21. const route = useRoute()
  22. // 通用函数:从菜单树中递归找出最匹配的 index
  23. function findBestMatch(menuList, path) {
  24. let bestMatch = ''
  25. function traverse(menus) {
  26. for (const item of menus) {
  27. const itemPath = getRoutePath(item)
  28. // 如果当前菜单的 path 是当前路径的前缀,可能是候选项
  29. if (path.startsWith(itemPath) && itemPath.length > bestMatch.length) {
  30. bestMatch = itemPath
  31. }
  32. if (item.children && item.children.length > 0) {
  33. traverse(item.children)
  34. }
  35. }
  36. }
  37. traverse(menuList)
  38. return bestMatch || path // fallback 到当前路径
  39. }
  40. // 响应式高亮菜单
  41. const activeMenu = computed(() => {
  42. return findBestMatch(menuList.value, route.path)
  43. })
  44. const router = useRouter()
  45. const imgrule1 = dmmn
  46. const messageVisible = ref(false)
  47. // 查看个人信息弹出框
  48. const openMessage = function () {
  49. messageVisible.value = true
  50. }
  51. // 关闭个人信息
  52. const closeMessage = function () {
  53. messageVisible.value = false
  54. }
  55. const message = function () {
  56. openMessage()
  57. }
  58. // 显示修改密码弹窗
  59. const showPasswordDialog = ref(false)
  60. const pwdRef = ref()
  61. //打开修改密码弹窗
  62. const openChangePassword = () => {
  63. showPasswordDialog.value = true
  64. }
  65. //关闭后清空密码表单
  66. function onPwdDialogClosed () {
  67. // 调用子组件暴露的 resetFields
  68. pwdRef.value?.resetFields()
  69. }
  70. function logout() {
  71. const machineId = localStorage.getItem('machineId')
  72. localStorage.removeItem('token')
  73. adminStore.clearState()
  74. router.push('/login?machineId=' + machineId)
  75. ElMessage.success('退出成功')
  76. }
  77. </script>
  78. <template>
  79. <div class="common-layout">
  80. <el-container>
  81. <el-aside style="
  82. width: 15%;
  83. max-width: 20%;
  84. position: fixed; /* 固定位置 */
  85. top: 0;
  86. left: 0;
  87. height: 100vh; /* 高度占满视口 */
  88. z-index: 100; /* 确保侧边栏在其他元素之上 */
  89. ">
  90. <div class="logo">
  91. <img src="../assets/新logo.png" alt="logo" style="width: 80px; height: 80px"/>
  92. <!-- <div style="font-size: 16px; font-weight: bold; color: black; text-align: center;" ><h1>海外金币管理系统</h1></div> -->
  93. </div>
  94. <el-card style="min-height: 90%;">
  95. <el-menu
  96. :router="true"
  97. class="el-menu-vertical-demo"
  98. :default-active="activeMenu"
  99. >
  100. <!-- 递归渲染菜单层级 -->
  101. <template v-for="menu in menuList" :key="menu.id">
  102. <!-- 有子菜单的父级菜单menuType=2 且存在children -->
  103. <el-sub-menu
  104. v-if="menu.children && menu.children.length > 0"
  105. :index="menu.id.toString()"
  106. >
  107. <template #title>
  108. <el-icon>
  109. <Folder/>
  110. </el-icon>
  111. <span>{{ menu.menuName }}</span>
  112. </template>
  113. <!-- 子菜单 -->
  114. <template v-for="child in menu.children" :key="child.id">
  115. <!-- 子菜单为叶子节点无children -->
  116. <el-menu-item
  117. v-if="!child.children || child.children.length === 0"
  118. :index="getRoutePath(child)"
  119. >
  120. <span>{{ child.menuName }}</span>
  121. </el-menu-item>
  122. <!-- 子菜单有下级 -->
  123. <el-sub-menu
  124. v-else
  125. :index="child.id.toString()"
  126. >
  127. <template #title>
  128. <span>{{ child.menuName }}</span>
  129. </template>
  130. <!-- 递归 下一级-->
  131. <template v-for="grandChild in child.children" :key="grandChild.id">
  132. <el-menu-item :index="getRoutePath(grandChild)">
  133. <span>{{ grandChild.menuName }}</span>
  134. </el-menu-item>
  135. </template>
  136. </el-sub-menu>
  137. </template>
  138. </el-sub-menu>
  139. <!-- 无子菜单的一级菜单 -->
  140. <el-menu-item
  141. v-else
  142. :index="getRoutePath(menu)"
  143. >
  144. <el-icon>
  145. <Folder/>
  146. </el-icon>
  147. <span>{{ menu.menuName }}</span>
  148. </el-menu-item>
  149. </template>
  150. </el-menu>
  151. </el-card>
  152. </el-aside>
  153. <el-container style="margin-left: 15%; min-width: 180px">
  154. <!-- 修改 el-header 样式 -->
  155. <el-header style="
  156. position: fixed;
  157. top: 0;
  158. left: 15%;
  159. right: 0;
  160. z-index: 80;
  161. background: white;
  162. ">
  163. <el-menu class="el-menu-demo" mode="horizontal" :ellipsis="false">
  164. <el-sub-menu index="1" class="admin">
  165. <template #title>
  166. <el-image :src="imgrule1" alt="错误" style="width: 50px; height: 50px"/>
  167. <span style="margin-left: 10px">{{ adminData.name }}</span>
  168. </template>
  169. <el-menu-item @click="message()">查看个人信息</el-menu-item>
  170. <el-menu-item @click="openChangePassword">修改密码</el-menu-item>
  171. <el-menu-item @click="logout">退出登录</el-menu-item>
  172. </el-sub-menu>
  173. </el-menu>
  174. </el-header>
  175. <el-main style="margin-top: 60px">
  176. <!-- 60px el-header 的大致高度可根据实际情况调整 -->
  177. <router-view></router-view>
  178. </el-main>
  179. </el-container>
  180. </el-container>
  181. <!-- 查看个人信息 -->
  182. <el-dialog v-model="messageVisible" title="查看个人信息" width="500px">
  183. <el-form :model="adminData">
  184. <el-form-item label="用户姓名" label-width="100px" label-position="left">
  185. <span class="message-font">{{ adminData.adminName }}</span>
  186. </el-form-item>
  187. <el-form-item label="精网号" label-width="100px" label-position="left">
  188. <span class="message-font">{{ adminData.account }}</span>
  189. </el-form-item>
  190. <el-form-item label="地区" label-width="100px" label-position="left">
  191. <span class="message-font">{{ adminData.markets }}</span>
  192. </el-form-item>
  193. <el-form-item label="注册时间" label-width="100px" label-position="left">
  194. <span class="message-font">{{ adminData.createTime }}</span>
  195. </el-form-item>
  196. </el-form>
  197. <template #footer>
  198. <div class="dialog-footer">
  199. <el-button text @click="closeMessage()">关闭</el-button>
  200. </div>
  201. </template>
  202. </el-dialog>
  203. <!-- 自定义密码修改弹窗组件 -->
  204. <el-dialog
  205. v-model="showPasswordDialog"
  206. :center="true"
  207. width="470px"
  208. @closed="onPwdDialogClosed"
  209. >
  210. <ChangePassword
  211. ref="pwdRef"
  212. @confirm="showPasswordDialog = false"
  213. />
  214. </el-dialog>
  215. </div>
  216. </template>
  217. <style scoped>
  218. .message-font {
  219. font-size: 16px;
  220. font-weight: bold;
  221. }
  222. .item {
  223. margin-top: 20px;
  224. margin-right: 40px;
  225. }
  226. .admin {
  227. margin-left: auto;
  228. }
  229. .el-aside {
  230. min-height: 100vh;
  231. width: 200px;
  232. }
  233. /* background-color: #BFD8D2; */
  234. .logo {
  235. margin: 20px 0px 20px 20px;
  236. display: flex;
  237. }
  238. .el-menu-demo {
  239. border: none;
  240. /* 去除边框 */
  241. padding: 0;
  242. /* 去除内边距 */
  243. float: right;
  244. /* 将菜单向右浮动 */
  245. }
  246. .el-menu-vertical-demo:not(.el-menu--collapse) {
  247. width: 240px;
  248. min-height: 400px;
  249. border: none;
  250. /* 去除边框 */
  251. }
  252. </style>