use-tabbar.ts 5.3 KB

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