提交 | 用户 | 时间
820397 1 <script lang="tsx">
H 2 import { usePermissionStore } from '@/store/modules/permission'
3 import { useAppStore } from '@/store/modules/app'
4
5 import { ElScrollbar } from 'element-plus'
6 import { Icon } from '@/components/Icon'
7 import { Menu } from '@/layout/components/Menu'
8 import { pathResolve } from '@/utils/routerHelper'
9 import { cloneDeep } from 'lodash-es'
10 import { filterMenusPath, initTabMap, tabPathMap } from './helper'
11 import { useDesign } from '@/hooks/web/useDesign'
12 import { isUrl } from '@/utils/is'
13
14 const { getPrefixCls, variables } = useDesign()
15
16 const prefixCls = getPrefixCls('tab-menu')
17
18 export default defineComponent({
19   name: 'TabMenu',
20   setup() {
21     const { push, currentRoute } = useRouter()
22
23     const { t } = useI18n()
24
25     const appStore = useAppStore()
26
27     const collapse = computed(() => appStore.getCollapse)
28
29     const fixedMenu = computed(() => appStore.getFixedMenu)
30
31     const permissionStore = usePermissionStore()
32
33     const routers = computed(() => permissionStore.getRouters)
34
35     const tabRouters = computed(() => unref(routers).filter((v) => !v?.meta?.hidden))
36
37     const setCollapse = () => {
38       appStore.setCollapse(!unref(collapse))
39     }
40
41     onMounted(() => {
42       if (unref(fixedMenu)) {
43         const path = `/${unref(currentRoute).path.split('/')[1]}`
44         const children = unref(tabRouters).find(
45           (v) =>
46             (v.meta?.alwaysShow || (v?.children?.length && v?.children?.length > 1)) &&
47             v.path === path
48         )?.children
49
50         tabActive.value = path
51         if (children) {
52           permissionStore.setMenuTabRouters(
53             cloneDeep(children).map((v) => {
54               v.path = pathResolve(unref(tabActive), v.path)
55               return v
56             })
57           )
58         }
59       }
60     })
61
62     watch(
63       () => routers.value,
64       (routers: AppRouteRecordRaw[]) => {
65         initTabMap(routers)
66         filterMenusPath(routers, routers)
67       },
68       {
69         immediate: true,
70         deep: true
71       }
72     )
73
74     const showTitle = ref(true)
75
76     watch(
77       () => collapse.value,
78       (collapse: boolean) => {
79         if (!collapse) {
80           setTimeout(() => {
81             showTitle.value = !collapse
82           }, 200)
83         } else {
84           showTitle.value = !collapse
85         }
86       }
87     )
88
89     // 是否显示菜单
90     const showMenu = ref(unref(fixedMenu) ? true : false)
91
92     // tab高亮
93     const tabActive = ref('')
94
95     // tab点击事件
96     const tabClick = (item: AppRouteRecordRaw) => {
97       if (isUrl(item.path)) {
98         window.open(item.path)
99         return
100       }
101       const newPath = item.children ? item.path : item.path.split('/')[0]
102       const oldPath = unref(tabActive)
103       tabActive.value = item.children ? item.path : item.path.split('/')[0]
104       if (item.children) {
105         if (newPath === oldPath || !unref(showMenu)) {
106           showMenu.value = unref(fixedMenu) ? true : !unref(showMenu)
107         }
108         if (unref(showMenu)) {
109           permissionStore.setMenuTabRouters(
110             cloneDeep(item.children).map((v) => {
111               v.path = pathResolve(unref(tabActive), v.path)
112               return v
113             })
114           )
115         }
116       } else {
117         push(item.path)
118         permissionStore.setMenuTabRouters([])
119         showMenu.value = false
120       }
121     }
122
123     // 设置高亮
124     const isActive = (currentPath: string) => {
125       const { path } = unref(currentRoute)
126       if (tabPathMap[currentPath].includes(path)) {
127         return true
128       }
129       return false
130     }
131
132     const mouseleave = () => {
133       if (!unref(showMenu) || unref(fixedMenu)) return
134       showMenu.value = false
135     }
136
137     return () => (
138       <div
139         id={`${variables.namespace}-menu`}
140         class={[
141           prefixCls,
3e359e 142           'relative bg-[var(--left-menu-bg-color)] layout-border__right',
820397 143           {
H 144             'w-[var(--tab-menu-max-width)]': !unref(collapse),
145             'w-[var(--tab-menu-min-width)]': unref(collapse)
146           }
147         ]}
148         onMouseleave={mouseleave}
149       >
3e359e 150         <ElScrollbar class="!h-[calc(100%-var(--tab-menu-collapse-height))]">
820397 151           <div>
H 152             {() => {
153               return unref(tabRouters).map((v) => {
154                 const item = (
155                   v.meta?.alwaysShow || (v?.children?.length && v?.children?.length > 1)
156                     ? v
157                     : {
158                         ...(v?.children && v?.children[0]),
159                         path: pathResolve(v.path, (v?.children && v?.children[0])?.path as string)
160                       }
161                 ) as AppRouteRecordRaw
162                 return (
163                   <div
164                     class={[
165                       `${prefixCls}__item`,
166                       'text-center text-12px relative py-12px cursor-pointer',
167                       {
168                         'is-active': isActive(v.path)
169                       }
170                     ]}
171                     onClick={() => {
172                       tabClick(item)
173                     }}
174                   >
175                     <div>
176                       <Icon icon={item?.meta?.icon}></Icon>
177                     </div>
178                     {!unref(showTitle) ? undefined : (
179                       <p class="mt-5px break-words px-2px">{t(item.meta?.title)}</p>
180                     )}
181                   </div>
182                 )
183               })
184             }}
185           </div>
186         </ElScrollbar>
187         <div
188           class={[
189             `${prefixCls}--collapse`,
190             'text-center h-[var(--tab-menu-collapse-height)] leading-[var(--tab-menu-collapse-height)] cursor-pointer'
191           ]}
192           onClick={setCollapse}
193         >
194           <Icon icon={unref(collapse) ? 'ep:d-arrow-right' : 'ep:d-arrow-left'}></Icon>
195         </div>
196         <Menu
197           class={[
198             '!absolute top-0 z-11',
199             {
200               '!left-[var(--tab-menu-min-width)]': unref(collapse),
201               '!left-[var(--tab-menu-max-width)]': !unref(collapse),
3e359e 202               '!w-[var(--left-menu-max-width)]': unref(showMenu) || unref(fixedMenu),
820397 203               '!w-0': !unref(showMenu) && !unref(fixedMenu)
H 204             }
205           ]}
206           style="transition: width var(--transition-time-02), left var(--transition-time-02);"
207         ></Menu>
208       </div>
209     )
210   }
211 })
212 </script>
213
214 <style lang="scss" scoped>
215 $prefix-cls: #{$namespace}-tab-menu;
216
217 .#{$prefix-cls} {
218   transition: all var(--transition-time-02);
219
220   &__item {
221     color: var(--left-menu-text-color);
222     transition: all var(--transition-time-02);
223
224     &:hover {
225       color: var(--left-menu-text-active-color);
226       // background-color: var(--left-menu-bg-active-color);
227     }
228   }
229
230   &--collapse {
231     color: var(--left-menu-text-color);
232     background-color: var(--left-menu-bg-light-color);
233   }
234
235   .is-active {
236     color: var(--left-menu-text-active-color);
237     background-color: var(--left-menu-bg-active-color);
238   }
239 }
240 </style>