use-tabbar.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import type { IContextMenuItem } from '@vben-core/tabs-ui';
  2. import type { TabDefinition } from '@vben-core/typings';
  3. import type {
  4. RouteLocationNormalized,
  5. RouteLocationNormalizedGeneric,
  6. } from 'vue-router';
  7. import { computed, ref, watch } from 'vue';
  8. import { useRoute, useRouter } from 'vue-router';
  9. import { useContentMaximize, useTabs } from '@vben-core/hooks';
  10. import {
  11. ArrowLeftToLine,
  12. ArrowRightLeft,
  13. ArrowRightToLine,
  14. ExternalLink,
  15. FoldHorizontal,
  16. Fullscreen,
  17. MdiPin,
  18. MdiPinOff,
  19. Minimize2,
  20. RotateCw,
  21. X,
  22. } from '@vben-core/icons';
  23. import { $t, useI18n } from '@vben-core/locales';
  24. import {
  25. storeToRefs,
  26. useCoreAccessStore,
  27. useCoreTabbarStore,
  28. } from '@vben-core/stores';
  29. import { filterTree } from '@vben-core/toolkit';
  30. export function useTabbar() {
  31. const router = useRouter();
  32. const route = useRoute();
  33. const accessStore = useCoreAccessStore();
  34. const coreTabbarStore = useCoreTabbarStore();
  35. const { accessMenus } = storeToRefs(accessStore);
  36. const { contentIsMaximize, toggleMaximize } = useContentMaximize();
  37. const {
  38. closeAllTabs,
  39. closeCurrentTab,
  40. closeLeftTabs,
  41. closeOtherTabs,
  42. closeRightTabs,
  43. closeTabByKey,
  44. getTabDisableState,
  45. openTabInNewWindow,
  46. refreshTab,
  47. toggleTabPin,
  48. } = useTabs();
  49. const currentActive = computed(() => {
  50. return route.path;
  51. });
  52. const { locale } = useI18n();
  53. const currentTabs = ref<RouteLocationNormalizedGeneric[]>();
  54. watch(
  55. [
  56. () => coreTabbarStore.getTabs,
  57. () => coreTabbarStore.updateTime,
  58. () => locale.value,
  59. ],
  60. ([tabs]) => {
  61. currentTabs.value = tabs.map((item) => wrapperTabLocale(item));
  62. },
  63. );
  64. /**
  65. * 初始化固定标签页
  66. */
  67. const initAffixTabs = () => {
  68. const affixTabs = filterTree(router.getRoutes(), (route) => {
  69. return !!route.meta?.affixTab;
  70. });
  71. coreTabbarStore.setAffixTabs(affixTabs);
  72. };
  73. // 点击tab,跳转路由
  74. const handleClick = (key: string) => {
  75. router.push(key);
  76. };
  77. // 关闭tab
  78. const handleClose = async (key: string) => {
  79. await closeTabByKey(key);
  80. };
  81. function wrapperTabLocale(tab: RouteLocationNormalizedGeneric) {
  82. return {
  83. ...tab,
  84. meta: {
  85. ...tab?.meta,
  86. title: $t(tab?.meta?.title as string),
  87. },
  88. };
  89. }
  90. watch(
  91. () => accessMenus.value,
  92. () => {
  93. initAffixTabs();
  94. },
  95. { immediate: true },
  96. );
  97. watch(
  98. () => route.path,
  99. () => {
  100. coreTabbarStore.addTab(route as RouteLocationNormalized);
  101. },
  102. { immediate: true },
  103. );
  104. const createContextMenus = (tab: TabDefinition) => {
  105. const {
  106. disabledCloseAll,
  107. disabledCloseCurrent,
  108. disabledCloseLeft,
  109. disabledCloseOther,
  110. disabledCloseRight,
  111. disabledRefresh,
  112. } = getTabDisableState(tab);
  113. const affixTab = tab?.meta?.affixTab ?? false;
  114. const menus: IContextMenuItem[] = [
  115. {
  116. disabled: disabledCloseCurrent,
  117. handler: async () => {
  118. await closeCurrentTab(tab);
  119. },
  120. icon: X,
  121. key: 'close',
  122. text: $t('preferences.tabbar.contextMenu.close'),
  123. },
  124. {
  125. handler: async () => {
  126. await toggleTabPin(tab);
  127. },
  128. icon: affixTab ? MdiPinOff : MdiPin,
  129. key: 'affix',
  130. text: affixTab
  131. ? $t('preferences.tabbar.contextMenu.unpin')
  132. : $t('preferences.tabbar.contextMenu.pin'),
  133. },
  134. {
  135. handler: async () => {
  136. if (!contentIsMaximize.value) {
  137. await router.push(tab.fullPath);
  138. }
  139. toggleMaximize();
  140. },
  141. icon: contentIsMaximize.value ? Minimize2 : Fullscreen,
  142. key: contentIsMaximize.value ? 'restore-maximize' : 'maximize',
  143. text: contentIsMaximize.value
  144. ? $t('preferences.tabbar.contextMenu.restoreMaximize')
  145. : $t('preferences.tabbar.contextMenu.maximize'),
  146. },
  147. {
  148. disabled: disabledRefresh,
  149. handler: refreshTab,
  150. icon: RotateCw,
  151. key: 'reload',
  152. text: $t('preferences.tabbar.contextMenu.reload'),
  153. },
  154. {
  155. handler: async () => {
  156. await openTabInNewWindow(tab);
  157. },
  158. icon: ExternalLink,
  159. key: 'open-in-new-window',
  160. separator: true,
  161. text: $t('preferences.tabbar.contextMenu.openInNewWindow'),
  162. },
  163. {
  164. disabled: disabledCloseLeft,
  165. handler: async () => {
  166. await closeLeftTabs(tab);
  167. },
  168. icon: ArrowLeftToLine,
  169. key: 'close-left',
  170. text: $t('preferences.tabbar.contextMenu.closeLeft'),
  171. },
  172. {
  173. disabled: disabledCloseRight,
  174. handler: async () => {
  175. await closeRightTabs(tab);
  176. },
  177. icon: ArrowRightToLine,
  178. key: 'close-right',
  179. separator: true,
  180. text: $t('preferences.tabbar.contextMenu.closeRight'),
  181. },
  182. {
  183. disabled: disabledCloseOther,
  184. handler: async () => {
  185. await closeOtherTabs(tab);
  186. },
  187. icon: FoldHorizontal,
  188. key: 'close-other',
  189. text: $t('preferences.tabbar.contextMenu.closeOther'),
  190. },
  191. {
  192. disabled: disabledCloseAll,
  193. handler: closeAllTabs,
  194. icon: ArrowRightLeft,
  195. key: 'close-all',
  196. text: $t('preferences.tabbar.contextMenu.closeAll'),
  197. },
  198. ];
  199. return menus;
  200. };
  201. return {
  202. createContextMenus,
  203. currentActive,
  204. currentTabs,
  205. handleClick,
  206. handleClose,
  207. };
  208. }