SubMenu.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <template v-for="subItem in menuList" :key="subItem.path">
  3. <el-sub-menu v-if="subItem.children?.length" :index="subItem.path">
  4. <template #title>
  5. <el-icon v-if="subItem.meta.icon">
  6. <component :is="subItem.meta.icon" />
  7. </el-icon>
  8. <span class="sle">{{ subItem.meta.title }}</span>
  9. </template>
  10. <SubMenu :menu-list="subItem.children" />
  11. </el-sub-menu>
  12. <el-menu-item v-else :index="subItem.path" @click="handleClickMenu(subItem)">
  13. <el-icon v-if="subItem.meta.icon">
  14. <component :is="subItem.meta.icon" />
  15. </el-icon>
  16. <template #title>
  17. <span class="sle">{{ subItem.meta.title }}</span>
  18. </template>
  19. </el-menu-item>
  20. </template>
  21. </template>
  22. <script setup lang="ts">
  23. import { useRouter } from "vue-router";
  24. import { ElMessage } from "element-plus";
  25. import { checkMenuClickPermission } from "@/utils/permission";
  26. defineProps<{ menuList: Menu.MenuOptions[] }>();
  27. const router = useRouter();
  28. const handleClickMenu = async (subItem: Menu.MenuOptions) => {
  29. if (subItem.meta.isLink) return window.open(subItem.meta.isLink, "_blank");
  30. if (!subItem.path) {
  31. ElMessage.warning("菜单路径不存在");
  32. return;
  33. }
  34. // 调用权限检查方法,判断是否可以点击(方法内部会显示相应的提示信息)
  35. const { canClick } = await checkMenuClickPermission(subItem.path);
  36. if (!canClick) {
  37. return;
  38. }
  39. // 允许访问,执行路由跳转
  40. try {
  41. await router.push(subItem.path);
  42. } catch (error: any) {
  43. handleRouteError(error);
  44. }
  45. };
  46. // 处理路由错误
  47. const handleRouteError = (error: any) => {
  48. // 如果是导航重复的错误,忽略它
  49. if (error?.name === "NavigationDuplicated") {
  50. return;
  51. }
  52. // 如果是路由不存在的错误
  53. if (error?.message?.includes("No match") || error?.message?.includes("not found")) {
  54. ElMessage.warning("该页面不存在或尚未配置");
  55. } else {
  56. console.error("路由跳转失败:", error);
  57. ElMessage.error("页面跳转失败,请稍后重试");
  58. }
  59. };
  60. </script>
  61. <style lang="scss">
  62. .el-sub-menu .el-sub-menu__title:hover {
  63. color: var(--el-menu-hover-text-color) !important;
  64. background-color: transparent !important;
  65. }
  66. .el-menu--collapse {
  67. .is-active {
  68. .el-sub-menu__title {
  69. color: #ffffff !important;
  70. background-color: var(--el-color-primary) !important;
  71. }
  72. }
  73. }
  74. .el-menu-item {
  75. &:hover {
  76. color: var(--el-menu-hover-text-color);
  77. }
  78. &.is-active {
  79. color: var(--el-menu-active-color) !important;
  80. background-color: var(--el-menu-active-bg-color) !important;
  81. &::before {
  82. position: absolute;
  83. top: 0;
  84. bottom: 0;
  85. width: 4px;
  86. content: "";
  87. background-color: var(--el-color-primary);
  88. }
  89. }
  90. }
  91. .vertical,
  92. .classic,
  93. .transverse {
  94. .el-menu-item {
  95. &.is-active {
  96. &::before {
  97. left: 0;
  98. }
  99. }
  100. }
  101. }
  102. .columns {
  103. .el-menu-item {
  104. &.is-active {
  105. &::before {
  106. right: 0;
  107. }
  108. }
  109. }
  110. }
  111. </style>