SideBar.vue 2.9 KB

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