index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <template>
  2. <!-- <div id="tabs-bar-container" class="tabs-bar-container">
  3. <el-tabs
  4. v-model="tabActive"
  5. class="tabs-content"
  6. type="card"
  7. @tab-click="handleTabClick"
  8. @tab-remove="handleTabRemove"
  9. >
  10. <el-tab-pane
  11. v-for="item in visitedRoutes"
  12. :key="item.path"
  13. :closable="!isAffix(item)"
  14. :label="item.meta.title"
  15. :name="item.path"
  16. ></el-tab-pane>
  17. </el-tabs>
  18. <el-dropdown @command="handleCommand">
  19. <span style="cursor: pointer">
  20. 更多操作
  21. <i class="el-icon-arrow-down el-icon--right"></i>
  22. </span>
  23. <el-dropdown-menu slot="dropdown" class="tabs-more">
  24. <el-dropdown-item command="closeOtherstabs">
  25. <vab-icon :icon="['fas', 'times-circle']" />
  26. 关闭其他
  27. </el-dropdown-item>
  28. <el-dropdown-item command="closeLefttabs">
  29. <vab-icon :icon="['fas', 'arrow-alt-circle-left']"></vab-icon>
  30. 关闭左侧
  31. </el-dropdown-item>
  32. <el-dropdown-item command="closeRighttabs">
  33. <vab-icon :icon="['fas', 'arrow-alt-circle-right']"></vab-icon>
  34. 关闭右侧
  35. </el-dropdown-item>
  36. <el-dropdown-item command="closeAlltabs">
  37. <vab-icon :icon="['fas', 'ban']"></vab-icon>
  38. 关闭全部
  39. </el-dropdown-item>
  40. </el-dropdown-menu>
  41. </el-dropdown>
  42. </div> -->
  43. <div></div>
  44. </template>
  45. <script>
  46. import path from 'path'
  47. import { mapGetters } from 'vuex'
  48. export default {
  49. name: 'VabTabsBar',
  50. data() {
  51. return {
  52. affixtabs: [],
  53. tabActive: '',
  54. }
  55. },
  56. computed: {
  57. ...mapGetters({
  58. visitedRoutes: 'tabsBar/visitedRoutes',
  59. routes: 'routes/routes',
  60. }),
  61. },
  62. watch: {
  63. $route: {
  64. handler(route) {
  65. this.inittabs()
  66. this.addtabs()
  67. let tabActive = ''
  68. this.visitedRoutes.forEach((item, index) => {
  69. if (item.path === this.$route.path) {
  70. tabActive = item.path
  71. }
  72. })
  73. this.tabActive = tabActive
  74. },
  75. immediate: true,
  76. },
  77. },
  78. mounted() {
  79. //console.log(this.visitedRoutes);
  80. },
  81. methods: {
  82. async handleTabRemove(tabActive) {
  83. let view
  84. this.visitedRoutes.forEach((item, index) => {
  85. if (tabActive == item.path) {
  86. view = item
  87. }
  88. })
  89. const { visitedRoutes } = await this.$store.dispatch(
  90. 'tabsBar/delRoute',
  91. view
  92. )
  93. if (this.isActive(view)) {
  94. this.toLastTag(visitedRoutes, view)
  95. }
  96. },
  97. handleTabClick(tab) {
  98. const route = this.visitedRoutes.filter((item, index) => {
  99. if (tab.index == index) return item
  100. })[0]
  101. if (this.$route.path !== route.path) {
  102. this.$router.push({
  103. path: route.path,
  104. query: route.query,
  105. fullPath: route.fullPath,
  106. })
  107. } else {
  108. return false
  109. }
  110. },
  111. isActive(route) {
  112. return route.path === this.$route.path
  113. },
  114. isAffix(tag) {
  115. return tag.meta && tag.meta.affix
  116. },
  117. filterAffixtabs(routes, basePath = '/') {
  118. let tabs = []
  119. routes.forEach((route) => {
  120. if (route.meta && route.meta.affix) {
  121. const tagPath = path.resolve(basePath, route.path)
  122. tabs.push({
  123. fullPath: tagPath,
  124. path: tagPath,
  125. name: route.name,
  126. meta: { ...route.meta },
  127. })
  128. }
  129. if (route.children) {
  130. const temptabs = this.filterAffixtabs(route.children, route.path)
  131. if (temptabs.length >= 1) {
  132. tabs = [...tabs, ...temptabs]
  133. }
  134. }
  135. })
  136. return tabs
  137. },
  138. inittabs() {
  139. const affixtabs = (this.affixtabs = this.filterAffixtabs(this.routes))
  140. for (const tag of affixtabs) {
  141. if (tag.name) {
  142. this.$store.dispatch('tabsBar/addVisitedRoute', tag)
  143. }
  144. }
  145. },
  146. addtabs() {
  147. const { name } = this.$route
  148. if (name) {
  149. this.$store.dispatch('tabsBar/addVisitedRoute', this.$route)
  150. }
  151. return false
  152. },
  153. handleCommand(command) {
  154. switch (command) {
  155. case 'refreshRoute':
  156. this.refreshRoute()
  157. break
  158. case 'closeOtherstabs':
  159. this.closeOtherstabs()
  160. break
  161. case 'closeLefttabs':
  162. this.closeLefttabs()
  163. break
  164. case 'closeRighttabs':
  165. this.closeRighttabs()
  166. break
  167. case 'closeAlltabs':
  168. this.closeAlltabs()
  169. break
  170. }
  171. },
  172. async refreshRoute() {
  173. this.$baseEventBus.$emit('reloadrouter-view')
  174. },
  175. async closeSelectedTag(view) {
  176. const { visitedRoutes } = await this.$store.dispatch(
  177. 'tabsBar/delRoute',
  178. view
  179. )
  180. if (this.isActive(view)) {
  181. this.toLastTag(visitedRoutes, view)
  182. }
  183. },
  184. async closeOtherstabs() {
  185. const view = await this.toThisTag()
  186. await this.$store.dispatch('tabsBar/delOthersRoutes', view)
  187. },
  188. async closeLefttabs() {
  189. const view = await this.toThisTag()
  190. await this.$store.dispatch('tabsBar/delLeftRoutes', view)
  191. },
  192. async closeRighttabs() {
  193. const view = await this.toThisTag()
  194. await this.$store.dispatch('tabsBar/delRightRoutes', view)
  195. },
  196. async closeAlltabs() {
  197. const view = await this.toThisTag()
  198. const { visitedRoutes } = await this.$store.dispatch(
  199. 'tabsBar/delAllRoutes'
  200. )
  201. if (this.affixtabs.some((tag) => tag.path === view.path)) {
  202. return
  203. }
  204. this.toLastTag(visitedRoutes, view)
  205. },
  206. toLastTag(visitedRoutes, view) {
  207. const latestView = visitedRoutes.slice(-1)[0]
  208. if (latestView) {
  209. this.$router.push(latestView)
  210. } else {
  211. this.$router.push('/')
  212. }
  213. },
  214. async toThisTag() {
  215. const view = this.visitedRoutes.filter((item, index) => {
  216. if (item.path === this.$route.fullPath) {
  217. return item
  218. }
  219. })[0]
  220. if (this.$route.path !== view.path) this.$router.push(view)
  221. return view
  222. },
  223. },
  224. }
  225. </script>
  226. <style lang="scss" scoped>
  227. .tabs-bar-container {
  228. position: relative;
  229. box-sizing: border-box;
  230. display: flex;
  231. align-content: center;
  232. align-items: center;
  233. justify-content: space-between;
  234. height: $base-tabs-bar-height;
  235. padding-right: $base-padding;
  236. padding-left: $base-padding;
  237. user-select: none;
  238. background: $base-color-white;
  239. border-top: 1px solid #f6f6f6;
  240. ::v-deep {
  241. .fold-unfold {
  242. margin-right: $base-padding;
  243. }
  244. }
  245. .tabs-content {
  246. width: calc(100% - 90px);
  247. height: $base-tag-item-height;
  248. ::v-deep {
  249. .el-tabs__nav-next,
  250. .el-tabs__nav-prev {
  251. height: $base-tag-item-height;
  252. line-height: $base-tag-item-height;
  253. }
  254. .el-tabs__header {
  255. border-bottom: 0;
  256. .el-tabs__nav {
  257. border: 0;
  258. }
  259. .el-tabs__item {
  260. box-sizing: border-box;
  261. height: $base-tag-item-height;
  262. margin-right: 5px;
  263. line-height: $base-tag-item-height;
  264. border: 1px solid $base-border-color;
  265. border-radius: $base-border-radius;
  266. transition: padding 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) !important;
  267. &.is-active {
  268. border: 1px solid $base-color-blue;
  269. }
  270. }
  271. }
  272. }
  273. }
  274. .more {
  275. display: flex;
  276. align-content: center;
  277. align-items: center;
  278. cursor: pointer;
  279. }
  280. }
  281. </style>