tabs.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import { useStorage } from '@vueuse/core'
  2. import { acceptHMRUpdate, defineStore } from 'pinia'
  3. import type { RouteRecordNameGeneric } from 'vue-router'
  4. export interface Tab {
  5. componentName?: string
  6. name?: RouteRecordNameGeneric
  7. icon?: string
  8. key: string
  9. label?: string
  10. locked?: boolean
  11. pinned?: boolean
  12. }
  13. export const useTabsStore = defineStore('tabsStore', () => {
  14. const tabs = useStorage<Tab[]>('tabs', [
  15. {
  16. componentName: 'Dashboard',
  17. icon: 'iconify-[mage--dashboard-chart]',
  18. key: '/dashboard',
  19. label: '仪表板',
  20. pinned: true,
  21. },
  22. ])
  23. const tabActiveKey = useStorage<string>('tabActiveKey', '')
  24. const tabsKeepAlive = useStorage<string[]>('tabsKeepAlive', [])
  25. const removeTabs = (keys: string[]) => {
  26. const keysSet = new Set(keys)
  27. const activeIndex = tabs.value.findIndex((tab) => tab.key === tabActiveKey.value)
  28. let newActiveKey = ''
  29. if (keysSet.has(tabActiveKey.value)) {
  30. for (let i = activeIndex + 1; i < tabs.value.length; i++) {
  31. if (!keysSet.has(tabs.value[i].key)) {
  32. newActiveKey = tabs.value[i].key
  33. break
  34. }
  35. }
  36. if (!newActiveKey) {
  37. for (let i = activeIndex - 1; i >= 0; i--) {
  38. if (!keysSet.has(tabs.value[i].key)) {
  39. newActiveKey = tabs.value[i].key
  40. break
  41. }
  42. }
  43. }
  44. if (newActiveKey) {
  45. setActive(newActiveKey)
  46. }
  47. }
  48. tabs.value = tabs.value.filter((tab) => !keysSet.has(tab.key))
  49. }
  50. function findTabIndex(key: string) {
  51. return tabs.value.findIndex((item) => item.key === key)
  52. }
  53. function getUnlockedTabKeysBefore(key: string) {
  54. const unlockedTabKeys: string[] = []
  55. for (const tab of tabs.value) {
  56. if (tab.key === key) break
  57. if (!tab.locked && !tab.pinned) {
  58. unlockedTabKeys.push(tab.key)
  59. }
  60. }
  61. return unlockedTabKeys
  62. }
  63. function getUnlockedTabKeysAfter(key: string) {
  64. const unlockedTabKeys: string[] = []
  65. for (let i = tabs.value.length - 1; i >= 0; i--) {
  66. if (tabs.value[i].key === key) break
  67. if (!tabs.value[i].locked && !tabs.value[i].pinned) {
  68. unlockedTabKeys.push(tabs.value[i].key)
  69. }
  70. }
  71. return unlockedTabKeys
  72. }
  73. function getUnlockedTabKeysExcept(key: string) {
  74. const unlockedTabKeys: string[] = []
  75. for (const tab of tabs.value) {
  76. if (tab.key !== key && !tab.locked && !tab.pinned) {
  77. unlockedTabKeys.push(tab.key)
  78. }
  79. }
  80. return unlockedTabKeys
  81. }
  82. function getUnlockedTabKeys() {
  83. const mutableTabKeys: string[] = []
  84. for (const tab of tabs.value) {
  85. if (!tab.locked && !tab.pinned) {
  86. mutableTabKeys.push(tab.key)
  87. }
  88. }
  89. return mutableTabKeys
  90. }
  91. function setTabs(value: Tab[]) {
  92. tabs.value = value
  93. }
  94. function setActive(key: string) {
  95. tabActiveKey.value = key
  96. }
  97. function createTab(tab: Tab) {
  98. const index = tabs.value.findIndex((item) => item.key === tab.key)
  99. if (index === -1) {
  100. tabs.value.push(tab)
  101. }
  102. setActive(tab.key)
  103. }
  104. const removeTab = (key: string) => {
  105. removeTabs([key])
  106. }
  107. const removeTabsBefore = (key: string) => {
  108. removeTabs(getUnlockedTabKeysBefore(key))
  109. }
  110. const removeTabsAfter = (key: string) => {
  111. removeTabs(getUnlockedTabKeysAfter(key))
  112. }
  113. const removeTabsExcept = (key: string) => {
  114. removeTabs(getUnlockedTabKeysExcept(key))
  115. }
  116. const removeAllTabs = () => {
  117. removeTabs(getUnlockedTabKeys())
  118. }
  119. const hasKeepAlive = (componentName?: string) => {
  120. const index = tabsKeepAlive.value.findIndex((item) => item === componentName)
  121. return index !== -1 ? true : false
  122. }
  123. const setKeepAlive = (componentName: string) => {
  124. const index = tabsKeepAlive.value.findIndex((item) => item === componentName)
  125. if (index !== -1) {
  126. tabsKeepAlive.value.splice(index, 1)
  127. } else {
  128. tabsKeepAlive.value.push(componentName)
  129. }
  130. }
  131. const isPinned = (key: string) => {
  132. const index = findTabIndex(key)
  133. return index !== -1 ? tabs.value[index].pinned : void 0
  134. }
  135. const isLocked = (key: string) => {
  136. const index = findTabIndex(key)
  137. return index !== -1 ? tabs.value[index].locked : void 0
  138. }
  139. const setLocked = (key: string) => {
  140. const index = findTabIndex(key)
  141. if (index !== -1) {
  142. tabs.value[index].locked = !tabs.value[index].locked
  143. }
  144. }
  145. return {
  146. tabs,
  147. tabActiveKey,
  148. tabsKeepAlive,
  149. createTab,
  150. getUnlockedTabKeys,
  151. getUnlockedTabKeysBefore,
  152. getUnlockedTabKeysExcept,
  153. getUnlockedTabKeysAfter,
  154. hasKeepAlive,
  155. isLocked,
  156. isPinned,
  157. removeAllTabs,
  158. removeTabsBefore,
  159. removeTabsExcept,
  160. removeTabsAfter,
  161. removeTab,
  162. setActive,
  163. setKeepAlive,
  164. setLocked,
  165. setTabs,
  166. }
  167. })
  168. if (import.meta.hot) {
  169. import.meta.hot.accept(acceptHMRUpdate(useTabsStore, import.meta.hot))
  170. }