use-tabs.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import type { IContextMenuItem } from '@vben-core/tabs-ui';
  2. import type { TabItem } 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 {
  10. IcRoundClose,
  11. IcRoundMultipleStop,
  12. IcRoundRefresh,
  13. MdiArrowExpandHorizontal,
  14. MdiFormatHorizontalAlignLeft,
  15. MdiFormatHorizontalAlignRight,
  16. MdiPin,
  17. MdiPinOff,
  18. } from '@vben-core/iconify';
  19. import { $t, useI18n } from '@vben-core/locales';
  20. import {
  21. storeToRefs,
  22. useCoreAccessStore,
  23. useCoreTabbarStore,
  24. } from '@vben-core/stores';
  25. import { filterTree } from '@vben-core/toolkit';
  26. function useTabs() {
  27. const router = useRouter();
  28. const route = useRoute();
  29. const accessStore = useCoreAccessStore();
  30. const coreTabbarStore = useCoreTabbarStore();
  31. const { accessMenus } = storeToRefs(accessStore);
  32. const currentActive = computed(() => {
  33. return route.path;
  34. });
  35. const { locale } = useI18n();
  36. const currentTabs = ref<RouteLocationNormalizedGeneric[]>();
  37. watch([() => coreTabbarStore.getTabs, () => locale.value], ([tabs, _]) => {
  38. currentTabs.value = tabs.map((item) => wrapperTabLocale(item));
  39. });
  40. /**
  41. * 初始化固定标签页
  42. */
  43. const initAffixTabs = () => {
  44. const affixTabs = filterTree(router.getRoutes(), (route) => {
  45. return !!route.meta?.affixTab;
  46. });
  47. coreTabbarStore.setAffixTabs(affixTabs);
  48. };
  49. // 点击tab,跳转路由
  50. const handleClick = (key: string) => {
  51. router.push(key);
  52. };
  53. // 关闭tab
  54. const handleClose = async (key: string) => {
  55. await coreTabbarStore.closeTabByKey(key, router);
  56. };
  57. function wrapperTabLocale(tab: RouteLocationNormalizedGeneric) {
  58. return {
  59. ...tab,
  60. meta: {
  61. ...tab.meta,
  62. title: $t(tab.meta.title as string),
  63. },
  64. };
  65. }
  66. watch(
  67. () => accessMenus.value,
  68. () => {
  69. initAffixTabs();
  70. },
  71. { immediate: true },
  72. );
  73. watch(
  74. () => route.path,
  75. () => {
  76. coreTabbarStore.addTab(route as RouteLocationNormalized);
  77. },
  78. { immediate: true },
  79. );
  80. const createContextMenus = (tab: TabItem) => {
  81. const tabs = coreTabbarStore.getTabs;
  82. const affixTabs = coreTabbarStore.affixTabs;
  83. const index = tabs.findIndex((item) => item.path === tab.path);
  84. const disabled = tabs.length <= 1;
  85. const { meta } = tab;
  86. const affixTab = meta?.affixTab ?? false;
  87. const isCurrentTab = route.path === tab.path;
  88. // 当前处于最左侧或者减去固定标签页的数量等于0
  89. const closeLeftDisabled =
  90. index === 0 || index - affixTabs.length <= 0 || !isCurrentTab;
  91. const closeRightDisabled = !isCurrentTab || index === tabs.length - 1;
  92. const closeOtherDisabled =
  93. disabled || !isCurrentTab || tabs.length - affixTabs.length <= 1;
  94. const menus: IContextMenuItem[] = [
  95. {
  96. disabled: !isCurrentTab,
  97. handler: async () => {
  98. await coreTabbarStore.refresh(router);
  99. },
  100. icon: IcRoundRefresh,
  101. key: 'reload',
  102. text: $t('preferences.tabbar.context-menu.reload'),
  103. },
  104. {
  105. disabled: !!affixTab || disabled,
  106. handler: async () => {
  107. await coreTabbarStore.closeTab(tab, router);
  108. },
  109. icon: IcRoundClose,
  110. key: 'close',
  111. text: $t('preferences.tabbar.context-menu.close'),
  112. },
  113. {
  114. handler: async () => {
  115. await (affixTab
  116. ? coreTabbarStore.unpinTab(tab)
  117. : coreTabbarStore.pinTab(tab));
  118. },
  119. icon: affixTab ? MdiPinOff : MdiPin,
  120. key: 'affix',
  121. separator: true,
  122. text: affixTab
  123. ? $t('preferences.tabbar.context-menu.unpin')
  124. : $t('preferences.tabbar.context-menu.pin'),
  125. },
  126. {
  127. disabled: closeLeftDisabled,
  128. handler: async () => {
  129. await coreTabbarStore.closeLeftTabs(tab);
  130. },
  131. icon: MdiFormatHorizontalAlignLeft,
  132. key: 'close-left',
  133. text: $t('preferences.tabbar.context-menu.close-left'),
  134. },
  135. {
  136. disabled: closeRightDisabled,
  137. handler: async () => {
  138. await coreTabbarStore.closeRightTabs(tab);
  139. },
  140. icon: MdiFormatHorizontalAlignRight,
  141. key: 'close-right',
  142. separator: true,
  143. text: $t('preferences.tabbar.context-menu.close-right'),
  144. },
  145. {
  146. disabled: closeOtherDisabled,
  147. handler: async () => {
  148. await coreTabbarStore.closeOtherTabs(tab);
  149. },
  150. icon: MdiArrowExpandHorizontal,
  151. key: 'close-other',
  152. text: $t('preferences.tabbar.context-menu.close-other'),
  153. },
  154. {
  155. disabled,
  156. handler: async () => {
  157. await coreTabbarStore.closeAllTabs(router);
  158. },
  159. icon: IcRoundMultipleStop,
  160. key: 'close-all',
  161. text: $t('preferences.tabbar.context-menu.close-all'),
  162. },
  163. // {
  164. // icon: 'icon-[material-symbols--back-to-tab-sharp]',
  165. // key: 'close-all',
  166. // text: '新窗口打开',
  167. // },
  168. ];
  169. return menus;
  170. };
  171. /**
  172. * 取消固定标签页
  173. */
  174. const handleUnpinTab = async (tab: TabItem) => {
  175. await coreTabbarStore.unpinTab(tab);
  176. };
  177. return {
  178. createContextMenus,
  179. currentActive,
  180. currentTabs,
  181. handleClick,
  182. handleClose,
  183. handleUnpinTab,
  184. };
  185. }
  186. export { useTabs };