tab-item.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template>
  2. <a-dropdown trigger="contextMenu" :popup-max-height="false" @select="actionSelect">
  3. <span class="arco-tag arco-tag-size-medium arco-tag-checked"
  4. :class="{ 'link-activated': itemData.fullPath === $route.fullPath }" @click="goto(itemData)">
  5. <span class="tag-link">
  6. {{ $t(itemData.title) }}
  7. </span>
  8. <span class="arco-icon-hover arco-tag-icon-hover arco-icon-hover-size-medium arco-tag-close-btn"
  9. @click.stop="tagClose(itemData, index)">
  10. <icon-close />
  11. </span>
  12. </span>
  13. <template #content>
  14. <a-doption :disabled="disabledReload" :value="Eaction.reload">
  15. <icon-refresh />
  16. <span>重新加载</span>
  17. </a-doption>
  18. <a-doption class="sperate-line" :disabled="disabledCurrent" :value="Eaction.current">
  19. <icon-close />
  20. <span>关闭当前标签页</span>
  21. </a-doption>
  22. <a-doption :disabled="disabledLeft" :value="Eaction.left">
  23. <icon-to-left />
  24. <span>关闭左侧标签页</span>
  25. </a-doption>
  26. <a-doption class="sperate-line" :disabled="disabledRight" :value="Eaction.right">
  27. <icon-to-right />
  28. <span>关闭右侧标签页</span>
  29. </a-doption>
  30. <a-doption :value="Eaction.others">
  31. <icon-swap />
  32. <span>关闭其它标签页</span>
  33. </a-doption>
  34. <a-doption :value="Eaction.all">
  35. <icon-folder-delete />
  36. <span>关闭全部标签页</span>
  37. </a-doption>
  38. </template>
  39. </a-dropdown>
  40. </template>
  41. <script lang="ts" setup>
  42. import { PropType, computed } from 'vue';
  43. import { useRouter, useRoute } from 'vue-router';
  44. import { useTabBarStore } from '@/store';
  45. import type { TagProps } from '@/store/modules/tab-bar/types';
  46. import { DEFAULT_ROUTE_NAME, REDIRECT_ROUTE_NAME } from '@/router/constants';
  47. // eslint-disable-next-line no-shadow
  48. enum Eaction {
  49. reload = 'reload',
  50. current = 'current',
  51. left = 'left',
  52. right = 'right',
  53. others = 'others',
  54. all = 'all',
  55. }
  56. const props = defineProps({
  57. itemData: {
  58. type: Object as PropType<TagProps>,
  59. default: () => ({})
  60. },
  61. index: {
  62. type: Number,
  63. default: 0,
  64. },
  65. });
  66. const router = useRouter();
  67. const route = useRoute();
  68. const tabBarStore = useTabBarStore();
  69. const goto = (tag: TagProps) => {
  70. router.push({ ...tag });
  71. };
  72. const tagList = computed(() => {
  73. return tabBarStore.getTabList;
  74. });
  75. const disabledReload = computed(() => {
  76. return props.itemData.fullPath !== route.fullPath;
  77. });
  78. const disabledCurrent = computed(() => {
  79. return props.index === 0;
  80. });
  81. const disabledLeft = computed(() => {
  82. return [0, 1].includes(props.index);
  83. });
  84. const disabledRight = computed(() => {
  85. return props.index === tagList.value.length - 1;
  86. });
  87. const tagClose = (tag: TagProps, idx: number) => {
  88. tabBarStore.deleteTag(idx, tag);
  89. if (props.itemData.fullPath === route.fullPath) {
  90. const latest = tagList.value[idx - 1]; // 获取队列的前一个tab
  91. router.push({ name: latest.name });
  92. }
  93. };
  94. const findCurrentRouteIndex = () => {
  95. return tagList.value.findIndex((el) => el.fullPath === route.fullPath);
  96. };
  97. const actionSelect = async (value: any) => {
  98. const { itemData, index } = props;
  99. const copyTagList = [...tagList.value];
  100. if (value === Eaction.current) {
  101. tagClose(itemData, index);
  102. } else if (value === Eaction.left) {
  103. const currentRouteIdx = findCurrentRouteIndex();
  104. copyTagList.splice(1, props.index - 1);
  105. tabBarStore.freshTabList(copyTagList);
  106. if (currentRouteIdx < index) {
  107. router.push({ name: itemData.name });
  108. }
  109. } else if (value === Eaction.right) {
  110. const currentRouteIdx = findCurrentRouteIndex();
  111. copyTagList.splice(props.index + 1);
  112. tabBarStore.freshTabList(copyTagList);
  113. if (currentRouteIdx > index) {
  114. router.push({ name: itemData.name });
  115. }
  116. } else if (value === Eaction.others) {
  117. const filterList = tagList.value.filter((el, idx) => {
  118. return idx === 0 || idx === props.index;
  119. });
  120. tabBarStore.freshTabList(filterList);
  121. router.push({ name: itemData.name });
  122. } else if (value === Eaction.reload) {
  123. tabBarStore.deleteCache(itemData);
  124. await router.push({
  125. name: REDIRECT_ROUTE_NAME,
  126. params: {
  127. path: route.fullPath,
  128. },
  129. });
  130. tabBarStore.addCache(itemData.name);
  131. } else {
  132. tabBarStore.resetTabList();
  133. router.push({ name: DEFAULT_ROUTE_NAME });
  134. }
  135. };
  136. </script>
  137. <style scoped lang="less">
  138. .tag-link {
  139. color: var(--color-text-2);
  140. text-decoration: none;
  141. }
  142. .link-activated {
  143. color: rgb(var(--link-6));
  144. .tag-link {
  145. color: rgb(var(--link-6));
  146. }
  147. &+.arco-tag-close-btn {
  148. color: rgb(var(--link-6));
  149. }
  150. }
  151. :deep(.arco-dropdown-option-content) {
  152. span {
  153. margin-left: 10px;
  154. }
  155. }
  156. .arco-dropdown-open {
  157. .tag-link {
  158. color: rgb(var(--danger-6));
  159. }
  160. .arco-tag-close-btn {
  161. color: rgb(var(--danger-6));
  162. }
  163. }
  164. .sperate-line {
  165. border-bottom: 1px solid var(--color-neutral-3);
  166. }
  167. </style>