SideBar.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <script setup lang="ts">
  2. import Logo from '@/components/Logo/Logo.vue'
  3. import {routes} from '@/routes'
  4. import {useRoute} from 'vue-router'
  5. import {computed, ref, watch} from 'vue'
  6. const route = useRoute()
  7. let openKeys = [openSub()]
  8. const selectedKey = ref([route.name])
  9. function openSub() {
  10. let path = route.path
  11. let lastSepIndex = path.lastIndexOf('/')
  12. return path.substring(1, lastSepIndex)
  13. }
  14. watch(route, () => {
  15. selectedKey.value = [route.name]
  16. const sub = openSub()
  17. const p = openKeys.indexOf(sub)
  18. if (p === -1) openKeys.push(sub)
  19. })
  20. const sidebars = computed(() => {
  21. return routes[0]['children']
  22. })
  23. interface meta {
  24. icon: any
  25. hiddenInSidebar: boolean
  26. }
  27. interface sidebar {
  28. path: string
  29. name: Function
  30. meta: meta,
  31. children: sidebar[]
  32. }
  33. const visible = computed(() => {
  34. const res: sidebar[] = [];
  35. (sidebars.value || []).forEach((s) => {
  36. if (s.meta && s.meta.hiddenInSidebar) {
  37. return
  38. }
  39. const t: sidebar = {
  40. path: s.path,
  41. name: s.name,
  42. meta: s.meta as meta,
  43. children: []
  44. };
  45. (s.children || []).forEach((c: any) => {
  46. if (c.meta && c.meta.hiddenInSidebar) {
  47. return
  48. }
  49. t.children.push((c as sidebar))
  50. })
  51. res.push(t)
  52. })
  53. return res
  54. })
  55. </script>
  56. <template>
  57. <div class="sidebar">
  58. <logo/>
  59. <a-menu
  60. :openKeys="openKeys"
  61. mode="inline"
  62. v-model:openKeys="openKeys"
  63. v-model:selectedKeys="selectedKey"
  64. >
  65. <template v-for="sidebar in visible">
  66. <a-menu-item v-if="sidebar.children.length===0 || sidebar.meta.hideChildren === true"
  67. :key="sidebar.name"
  68. @click="$router.push('/'+sidebar.path).catch(() => {})">
  69. <component :is="sidebar.meta.icon"/>
  70. <span>{{ sidebar.name() }}</span>
  71. </a-menu-item>
  72. <a-sub-menu v-else :key="sidebar.path">
  73. <template #title>
  74. <component :is="sidebar.meta.icon"/>
  75. <span>{{ sidebar.name() }}</span>
  76. </template>
  77. <a-menu-item v-for="child in sidebar.children" :key="child.name">
  78. <router-link :to="'/'+sidebar.path+'/'+child.path">
  79. {{ child.name() }}
  80. </router-link>
  81. </a-menu-item>
  82. </a-sub-menu>
  83. </template>
  84. </a-menu>
  85. </div>
  86. </template>
  87. <style lang="less">
  88. .ant-layout-sider-collapsed .logo {
  89. overflow: hidden;
  90. }
  91. .ant-menu-inline, .ant-menu-vertical, .ant-menu-vertical-left {
  92. border-right: unset;
  93. }
  94. </style>