index.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <template>
  2. <div class="tabs">
  3. <el-scrollbar class="scroll-container tags-view-container" ref="scrollbarDom">
  4. <Item
  5. v-for="menu in menuList"
  6. :key="menu.meta.title"
  7. :menu="menu"
  8. :active="activeMenu.path === menu.path"
  9. @close="delMenu(menu)"
  10. @reload="pageReload"
  11. />
  12. </el-scrollbar>
  13. <div class="handle">
  14. <el-dropdown placement="bottom">
  15. <div class="el-dropdown-link">
  16. <i class="iconfont icon-xialajiantouxiao"></i>
  17. </div>
  18. <template #dropdown>
  19. <el-dropdown-menu>
  20. <el-dropdown-item @click="pageReload">重新加载</el-dropdown-item>
  21. <el-dropdown-item :disabled="currentDisabled" @click="closeCurrentRoute">关闭当前标签</el-dropdown-item>
  22. <el-dropdown-item :disabled="menuList.length < 3" @click="closeOtherRoute">关闭其他标签</el-dropdown-item>
  23. <el-dropdown-item :disabled="menuList.length <= 1" @click="closeAllRoute">关闭所有标签</el-dropdown-item>
  24. </el-dropdown-menu>
  25. </template>
  26. </el-dropdown>
  27. <i class="iconfont" :class="contentFullScreen?'icon-tuichuquanping':'icon-quanping1'" @click="onFullscreen"></i>
  28. </div>
  29. </div>
  30. </template>
  31. <script>
  32. import { defineComponent, computed, unref, watch, reactive, ref, nextTick } from 'vue'
  33. import Item from './item.vue'
  34. import { useStore } from 'vuex'
  35. import { useRoute, useRouter } from 'vue-router'
  36. import tabsHook from './tabsHook'
  37. export default defineComponent({
  38. components: {
  39. Item
  40. },
  41. setup() {
  42. const store = useStore()
  43. const route = useRoute()
  44. const router = useRouter()
  45. const scrollbarDom = ref(null)
  46. const allRoutes = router.options.routes
  47. const defaultMenu = {
  48. path: '/classifyManageIndex',
  49. meta: { title: '牛只分类', hideClose: true }
  50. }
  51. const contentFullScreen = computed(() => store.state.app.contentFullScreen)
  52. const currentDisabled = computed(() => route.path === defaultMenu.path)
  53. let activeMenu = reactive({ path: '' })
  54. let menuList = ref(tabsHook.getItem())
  55. if (menuList.value.length === 0) { // 判断之前有没有调用过
  56. addMenu(defaultMenu)
  57. }
  58. watch(menuList.value, (newVal) => {
  59. tabsHook.setItem(newVal)
  60. })
  61. watch(menuList, (newVal) => {
  62. tabsHook.setItem(newVal)
  63. })
  64. router.afterEach(() => {
  65. addMenu(route)
  66. initMenu(route)
  67. })
  68. // 全屏
  69. function onFullscreen() {
  70. store.commit('app/contentFullScreenChange', !contentFullScreen.value)
  71. }
  72. // 当前页面组件重新加载
  73. function pageReload() {
  74. const self = route.matched[route.matched.length-1].instances.default
  75. // console.log(route.matched);
  76. self.handleReload();
  77. // const { fullPath, meta, name } = unref(route);
  78. // if (meta.cache && name) {
  79. // store.commit('keepAlive/delKeepAliveComponentsName', name)
  80. // }
  81. // router.replace({
  82. // path: "/redirect" + fullPath
  83. // });
  84. }
  85. // 关闭当前标签,首页不关闭
  86. function closeCurrentRoute() {
  87. if (route.path !== defaultMenu.path) {
  88. delMenu(route)
  89. }
  90. }
  91. // 关闭除了当前标签之外的所有标签
  92. function closeOtherRoute() {
  93. menuList.value = [defaultMenu]
  94. if (route.path !== defaultMenu.path) {
  95. addMenu(route)
  96. }
  97. setKeepAliveData()
  98. }
  99. // 关闭所有的标签,除了首页
  100. function closeAllRoute() {
  101. menuList.value = [defaultMenu]
  102. setKeepAliveData()
  103. router.push(defaultMenu.path)
  104. }
  105. // 添加新的菜单项
  106. function addMenu(menu) {
  107. let { path, meta, name } = menu
  108. if (meta.hideTabs) {
  109. return
  110. }
  111. let hasMenu = menuList.value.some((obj) => {
  112. return obj.path === path
  113. })
  114. if (!hasMenu) {
  115. menuList.value.push({
  116. path,
  117. meta,
  118. name
  119. })
  120. }
  121. }
  122. // 删除菜单项
  123. function delMenu(menu) {
  124. let index = 0
  125. if (!menu.meta.hideClose) {
  126. if (menu.meta.cache && menu.name) {
  127. store.commit('keepAlive/delKeepAliveComponentsName', menu.name)
  128. }
  129. index = menuList.value.findIndex((item) => item.path === menu.path)
  130. menuList.value.splice(index, 1)
  131. }
  132. if (menu.path === activeMenu.path) {
  133. index - 1 > 0 ? router.push(menuList.value[index - 1].path) : router.push(defaultMenu.path)
  134. }
  135. }
  136. // 初始化activeMenu
  137. function initMenu(menu) {
  138. activeMenu = menu
  139. nextTick(() => {
  140. // setPosition()
  141. })
  142. }
  143. // 设置当前滚动条应该在的位置
  144. function setPosition() {
  145. console.log('查看当前什么值',scrollbarDom);
  146. if (scrollbarDom.value) {
  147. const domBox = {
  148. scrollbar: scrollbarDom.value.scrollbar.querySelector('.el-scrollbar__wrap '),
  149. activeDom: scrollbarDom.value.scrollbar.querySelector('.active'),
  150. activeFather: scrollbarDom.value.scrollbar.querySelector('.el-scrollbar__view')
  151. }
  152. for (let i in domBox) {
  153. if (!domBox[i]) {
  154. return
  155. }
  156. }
  157. const domData = {
  158. scrollbar: domBox.scrollbar.getBoundingClientRect(),
  159. activeDom: domBox.activeDom.getBoundingClientRect(),
  160. activeFather: domBox.activeFather.getBoundingClientRect()
  161. }
  162. const num = domData.activeDom.x - domData.activeFather.x + 1/2 * domData.activeDom.width - 1/2 * domData.scrollbar.width
  163. domBox.scrollbar.scrollLeft = num
  164. }
  165. }
  166. // 配置需要缓存的数据
  167. function setKeepAliveData() {
  168. let keepAliveNames = []
  169. menuList.value.forEach((menu) => {
  170. menu.meta && menu.meta.cache && menu.name && keepAliveNames.push(menu.name)
  171. })
  172. store.commit('keepAlive/setKeepAliveComponentsName', keepAliveNames)
  173. }
  174. // 初始化时调用:1. 新增菜单 2. 初始化activeMenu
  175. addMenu(route)
  176. initMenu(route)
  177. return {
  178. contentFullScreen,
  179. onFullscreen,
  180. pageReload,
  181. scrollbarDom,
  182. // 菜单相关
  183. menuList,
  184. activeMenu,
  185. delMenu,
  186. closeCurrentRoute,
  187. closeOtherRoute,
  188. closeAllRoute,
  189. currentDisabled
  190. }
  191. }
  192. })
  193. </script>
  194. <style lang="scss" scoped>
  195. .tabs {
  196. display: flex;
  197. justify-content: space-between;
  198. align-items: center;
  199. height: 40px;
  200. background: var(--system-header-background);
  201. border-bottom: 1px solid var(--system-header-border-color);
  202. border-top: 1px solid var(--system-header-border-color);
  203. border-left: 1px solid var(--system-header-border-color);
  204. box-shadow: 0 1px 4px 0 rgba(0, 0, 0, .1);
  205. .handle {
  206. min-width: 95px;
  207. height: 100%;
  208. display: flex;
  209. align-items: center;
  210. .el-dropdown-link {
  211. margin-top: 5px;
  212. border-left: 1px solid var(--system-header-border-color);
  213. height: 25px;
  214. width: 40px;
  215. display: flex;
  216. justify-content: center;
  217. align-items: center;
  218. }
  219. i {
  220. color: var(--system-header-text-color);
  221. }
  222. }
  223. }
  224. .scroll-container {
  225. white-space: nowrap;
  226. position: relative;
  227. overflow: hidden;
  228. width: 100%;
  229. :deep {
  230. .el-scrollbar__bar {
  231. bottom: 0px;
  232. }
  233. .el-scrollbar__wrap {
  234. height: 49px;
  235. }
  236. }
  237. }
  238. .tags-view-container {
  239. height: 34px;
  240. flex: 1;
  241. width: 100%;
  242. display: flex;
  243. }
  244. .el-icon-full-screen {
  245. cursor: pointer;
  246. &:hover {
  247. background: rgba(0,0,0,.025);
  248. }
  249. &:focus {
  250. outline: none;
  251. }
  252. }
  253. </style>