index.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <div class="c-sidebar">
  3. <div class="c-sidebar__header">
  4. <router-link
  5. tag="img"
  6. class="u-pointer"
  7. src="/logo.png"
  8. to="/"
  9. />
  10. </div>
  11. <el-scrollbar
  12. class="c-sidebar__menu"
  13. wrap-class="c-sidebar__wrapper"
  14. >
  15. <el-menu
  16. mode="vertical"
  17. :default-active="activeMenu"
  18. text-color="#a5aec7"
  19. active-text-color="#fff"
  20. :unique-opened="false"
  21. :collapse-transition="false"
  22. >
  23. <sidebar-item
  24. v-for="route in routers"
  25. :key="route.path"
  26. :item="route"
  27. />
  28. </el-menu>
  29. </el-scrollbar>
  30. </div>
  31. </template>
  32. <script>
  33. import path from 'path'
  34. import { mapGetters } from 'vuex'
  35. import SidebarItem from './SidebarItem'
  36. function resolve (...args) {
  37. return path.resolve(...args)
  38. }
  39. function filterRoutes (routes, basePath) {
  40. const res = []
  41. routes.forEach(route => {
  42. if (route.hidden) {
  43. return
  44. }
  45. const { name, meta = {} } = route
  46. const path = basePath ? resolve(basePath, route.path) : route.path
  47. let children = route.children
  48. if (children) {
  49. children = filterRoutes(children, path)
  50. if (!children.length) {
  51. return
  52. }
  53. if (children.length === 1) {
  54. const { path: cpath, name: cname, meta: cmeta = {} } = children[0]
  55. res.push({ path: resolve(path, cpath), name: cname, meta: { ...meta, ...cmeta } })
  56. return
  57. }
  58. res.push({ path, name, meta, children })
  59. } else {
  60. res.push({ path, name, meta })
  61. }
  62. })
  63. return res
  64. }
  65. export default {
  66. name: 'Sidebar',
  67. components: { SidebarItem },
  68. computed: {
  69. ...mapGetters(['permissionRoutes']),
  70. routers () {
  71. // 暂时只考虑两层
  72. return filterRoutes(this.permissionRoutes)
  73. },
  74. activeMenu () {
  75. const path = this.$route.matched[1]?.path
  76. return path?.replace(/\/$/, '')
  77. }
  78. }
  79. }
  80. </script>
  81. <style lang="scss" scoped>
  82. .c-sidebar {
  83. display: inline-flex;
  84. flex-direction: column;
  85. width: 240px;
  86. background-color: #fff;
  87. box-shadow: 1px 0 4px rgba(0, 21, 41, 0.08);
  88. z-index: 9;
  89. &__header {
  90. flex: none;
  91. padding: 32px 0 24px;
  92. text-align: center;
  93. }
  94. &__menu {
  95. flex: 1 1 auto;
  96. min-height: 0.5;
  97. ::v-deep {
  98. .c-sidebar__wrapper {
  99. margin-right: -7px !important;
  100. overflow-x: hidden;
  101. }
  102. .el-scrollbar__bar {
  103. display: none;
  104. }
  105. .el-menu {
  106. width: 100%;
  107. }
  108. .el-menu-item,
  109. .el-submenu__title {
  110. display: flex;
  111. align-items: center;
  112. }
  113. .nest-menu .el-menu-item {
  114. padding-left: 48px !important;
  115. }
  116. .el-menu-item,
  117. .el-submenu__title,
  118. .el-icon-arrow-down {
  119. font-weight: bold;
  120. }
  121. .el-menu-item.is-active {
  122. color: #fff !important;
  123. background-color: $blue !important;
  124. }
  125. .is-active > .el-submenu__title,
  126. .is-active > .el-submenu__title > .el-icon-arrow-down {
  127. color: $blue !important;
  128. }
  129. .svg-icon {
  130. margin-right: 8px;
  131. color: inherit;
  132. font-size: 20px;
  133. }
  134. .sub-el-icon {
  135. color: inherit;
  136. width: 20px;
  137. height: 22px;
  138. margin-right: 8px;
  139. }
  140. }
  141. }
  142. }
  143. </style>