index.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { ref, defineComponent, PropType, computed, watch } from 'vue'
  2. // import { Menu } from 'element-plus'
  3. import { useRouter } from 'vue-router'
  4. import type { RouteRecordRaw, RouteLocationNormalizedLoaded } from 'vue-router'
  5. import Scrollbar from '_c/Scrollbar/index.vue'
  6. import Item from './Item.vue'
  7. import { permissionStore } from '_p/index/store/modules/permission'
  8. import { setSidebarItem } from './hooks/setSidebarItem'
  9. import { isExternal } from '@/utils/validate'
  10. import { findIndex } from '@/utils'
  11. import config from '_p/index/config'
  12. const { show_logo } = config
  13. import './index.less'
  14. export default defineComponent({
  15. name: 'Silder',
  16. components: {
  17. Scrollbar,
  18. Item
  19. },
  20. props: {
  21. collapsed: {
  22. type: Boolean as PropType<boolean>,
  23. default: true
  24. },
  25. inlineIndent: {
  26. type: Number as PropType<number>,
  27. default: 24
  28. },
  29. forceSubMenuRender: {
  30. type: Boolean as PropType<boolean>,
  31. default: false
  32. },
  33. mode: {
  34. type: String as PropType<'vertical' | 'horizontal' | 'vertical-right' | 'inline'>,
  35. default: 'inline'
  36. },
  37. theme: {
  38. type: String as PropType<'light' | 'dark'>,
  39. default: 'dark'
  40. }
  41. },
  42. setup(props) {
  43. const { currentRoute, push } = useRouter()
  44. const { resolvePath, treeFindRouter, getFullPath, findCurrentRoute } = setSidebarItem()
  45. const routers = computed((): RouteRecordRaw[] => {
  46. return permissionStore.routers
  47. })
  48. const selectedKeys = ref<string[]>([])
  49. const openKeys = ref<string[]>([])
  50. const activeMenuName = ref<string>('')
  51. watch(
  52. () => currentRoute.value,
  53. (route: RouteLocationNormalizedLoaded) => {
  54. setSelectedKeys(route)
  55. },
  56. {
  57. immediate: true
  58. }
  59. )
  60. watch(
  61. () => props.collapsed,
  62. (collapsed: boolean) => {
  63. setOpenKeys(currentRoute.value, collapsed)
  64. },
  65. {
  66. immediate: true
  67. }
  68. )
  69. function handleOpenChange(keyArr: string[]) {
  70. // 需要自己管理openKeys
  71. openKeys.value = keyArr
  72. }
  73. function setOpenKeys(route: RouteLocationNormalizedLoaded, collapsed: boolean) {
  74. let currentRoute: any = null
  75. if (route.meta.activeMenu) {
  76. currentRoute = findCurrentRoute(routers.value, route.meta.activeMenu)
  77. } else {
  78. currentRoute = route
  79. }
  80. const parentRoute: RouteRecordRaw[] = treeFindRouter(permissionStore.routers, (data: any) => data.name === currentRoute.name)
  81. openKeys.value = collapsed ? [] : getFullPath(parentRoute.map((v: RouteRecordRaw) => v.path))
  82. }
  83. function setSelectedKeys(route: RouteLocationNormalizedLoaded) {
  84. const { meta, path, name } = route
  85. activeMenuName.value = name as string
  86. if (meta.activeMenu) {
  87. selectedKeys.value = [meta.activeMenu]
  88. return
  89. }
  90. selectedKeys.value = [path]
  91. }
  92. function highlightMenu(className: string, basePath: string) {
  93. const parentRoute: RouteRecordRaw[] = treeFindRouter(permissionStore.routers, (data: any) => data.name === currentRoute.value.name)
  94. const parentFullPath: string[] = getFullPath(parentRoute.map((v: RouteRecordRaw) => v.path))
  95. return findIndex(parentFullPath, (item: string) => item === basePath) !== -1 ? className : ''
  96. }
  97. function handleMenuClick({ key }: any) {
  98. console.log(key)
  99. if (isExternal(key)) {
  100. window.open(key)
  101. } else {
  102. push({ path: key })
  103. }
  104. }
  105. // function renderMenu(routers: RouteRecordRaw[], basePath = '/') {
  106. // if (routers && routers.length) {
  107. // return routers.map((item: RouteRecordRaw) => {
  108. // if (!item.meta?.hidden) {
  109. // const _basePath = resolvePath(basePath, item.path)
  110. // const { onlyOneChild, hasOneShowingChild } = setSidebarItem()
  111. // if (hasOneShowingChild(item.children, item) && (!onlyOneChild.value.children || onlyOneChild.value.noShowingChildren) && !item.meta?.alwaysShow) {
  112. // return (
  113. // <Menu.Item key={resolvePath(_basePath, onlyOneChild.value.path)} v-slots={{
  114. // default: () => [
  115. // <Item
  116. // icon={onlyOneChild.value.meta && onlyOneChild.value.meta.icon}
  117. // title={onlyOneChild.value.meta?.title}
  118. // />
  119. // ]
  120. // }}>
  121. // </Menu.Item>
  122. // )
  123. // } else {
  124. // return (
  125. // <Menu.SubMenu
  126. // key={_basePath}
  127. // class={highlightMenu(props.theme + '-active-item', _basePath)}
  128. // popupClassName={highlightMenu(props.theme + '-popup-active-item', _basePath)}
  129. // v-slots={{
  130. // title: () => [
  131. // <Item
  132. // icon={item.meta && item.meta.icon}
  133. // title={item.meta?.title}
  134. // />
  135. // ]
  136. // }}
  137. // >
  138. // {renderMenu(item.children as any, _basePath)}
  139. // </Menu.SubMenu>
  140. // )
  141. // }
  142. // }
  143. // })
  144. // }
  145. // }
  146. // return () => {
  147. // return (
  148. // // <div class={{ 'has-logo': show_logo, 'sidebar-container': true }}>
  149. // // <scrollbar class='menu-wrap'>
  150. // // <Menu
  151. // // selectedKeys={selectedKeys.value}
  152. // // openKeys={openKeys.value}
  153. // // theme={props.theme}
  154. // // mode={props.mode}
  155. // // onClick={handleMenuClick}
  156. // // onOpenChange={handleOpenChange}
  157. // // >
  158. // // {renderMenu(routers.value)}
  159. // // </Menu>
  160. // // </scrollbar>
  161. // // </div>
  162. // )
  163. // }
  164. }
  165. })