diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue index f3f1b8f..4a2cb38 100644 --- a/src/layout/components/TagsView/index.vue +++ b/src/layout/components/TagsView/index.vue @@ -30,27 +30,26 @@
-
- - +
@@ -87,7 +86,6 @@ computed, ref, toRefs, - toRaw, unref, provide, watch, @@ -113,7 +111,7 @@ LeftOutlined, RightOutlined, } from '@vicons/antd'; - import { renderIcon } from '@/utils/index'; + import { renderIcon } from '@/utils'; import elementResizeDetectorMaker from 'element-resize-detector'; import { useDesignSetting } from '@/hooks/setting/useDesignSetting'; import { useProjectSettingStore } from '@/store/modules/projectSetting'; @@ -143,7 +141,6 @@ const router = useRouter(); const tabsViewStore = useTabsViewStore(); const asyncRouteStore = useAsyncRouteStore(); - const navRef: any = ref(null); const navScroll: any = ref(null); const navWrap: any = ref(null); const isCurrent = ref(false); @@ -151,9 +148,6 @@ const state = reactive({ activeKey: route.fullPath, scrollable: false, - navStyle: { - transform: '', - }, dropdownX: 0, dropdownY: 0, showDropdown: false, @@ -172,10 +166,7 @@ const currentRoute = useRoute(); const navMode = unref(getNavMode); if (unref(navMode) != 'horizontal-mix') return true; - if (unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot) { - return false; - } - return true; + return !(unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot); }); //动态组装样式 菜单缩进 @@ -198,7 +189,7 @@ //tags 右侧下拉菜单 const TabsMenuOptions = computed(() => { - const isDisabled = unref(tabsList).length <= 1 ? true : false; + const isDisabled = unref(tabsList).length <= 1; return [ { label: '刷新当前', @@ -245,11 +236,11 @@ document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; // 滚动条偏移量 - if (!getHeaderSetting.fixed && getMultiTabsSetting.fixed && scrollTop >= 64) { - state.isMultiHeaderFixed = true; - } else { - state.isMultiHeaderFixed = false; - } + state.isMultiHeaderFixed = !!( + !getHeaderSetting.fixed && + getMultiTabsSetting.fixed && + scrollTop >= 64 + ); } window.addEventListener('scroll', onScroll, true); @@ -281,7 +272,7 @@ if (whiteList.includes(route.name as string)) return; state.activeKey = to; tabsViewStore.addTabs(getSimpleRoute(route)); - updateNavScroll(); + updateNavScroll(true); }, { immediate: true } ); @@ -374,64 +365,73 @@ state.showDropdown = false; }; - function getCurrentScrollOffset() { - const { navStyle } = state; - const transform: any = toRaw(navStyle.transform); - return transform ? Number(transform.match(/translateX\(-(\d+(\.\d+)*)px\)/)[1]) : 0; - } - - function setOffset(value) { - state.navStyle.transform = `translateX(-${value}px)`; + /** + * @param value 要滚动到的位置 + * @param amplitude 每次滚动的长度 + */ + function scrollTo(value: number, amplitude: number) { + const currentScroll = navScroll.value.scrollLeft; + const scrollWidth = + (amplitude > 0 && currentScroll + amplitude >= value) || + (amplitude < 0 && currentScroll + amplitude <= value) + ? value + : currentScroll + amplitude; + navScroll.value && navScroll.value.scrollTo(scrollWidth, 0); + if (scrollWidth === value) return; + return window.requestAnimationFrame(() => scrollTo(value, amplitude)); } function scrollPrev() { const containerWidth = navScroll.value.offsetWidth; - const currentOffset = getCurrentScrollOffset(); - if (!currentOffset) return; - let newOffset = currentOffset > containerWidth ? currentOffset - containerWidth : 0; - setOffset(newOffset); + const currentScroll = navScroll.value.scrollLeft; + + if (!currentScroll) return; + const scrollLeft = currentScroll > containerWidth ? currentScroll - containerWidth : 0; + scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20); } function scrollNext() { - const navWidth = navRef.value.scrollWidth; const containerWidth = navScroll.value.offsetWidth; - const currentOffset = getCurrentScrollOffset(); - if (navWidth - currentOffset <= containerWidth) return; + const navWidth = navScroll.value.scrollWidth; + const currentScroll = navScroll.value.scrollLeft; - let newOffset = - navWidth - currentOffset > containerWidth * 2 - ? currentOffset + containerWidth + if (navWidth - currentScroll <= containerWidth) return; + const scrollLeft = + navWidth - currentScroll > containerWidth * 2 + ? currentScroll + containerWidth : navWidth - containerWidth; - - setOffset(newOffset); + scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20); } - function updateNavScroll() { - if (!navRef.value) return; - let navWidth = navRef.value.scrollWidth; - let containerWidth = navScroll.value.offsetWidth; - const currentOffset = getCurrentScrollOffset(); + /** + * @param autoScroll 是否开启自动滚动功能 + */ + async function updateNavScroll(autoScroll?: boolean) { + await nextTick(); + if (!navScroll.value) return; + const containerWidth = navScroll.value.offsetWidth; + const navWidth = navScroll.value.scrollWidth; + if (containerWidth < navWidth) { state.scrollable = true; - if (navWidth - currentOffset < containerWidth) { - setOffset(navWidth - containerWidth); + if (autoScroll) { + let tagList = navScroll.value.querySelectorAll('.tabs-card-scroll-item') || []; + [...tagList].forEach((tag: HTMLElement) => { + // fix SyntaxError + if (tag.id === `tag${state.activeKey.split('/').join('\/')}`) { + tag.scrollIntoView && tag.scrollIntoView(); + } + }); } } else { state.scrollable = false; - if (currentOffset > 0) { - setOffset(0); - } } } function handleResize() { - updateNavScroll(); + updateNavScroll(true); } - const getNavStyle = computed(() => { - return state.navStyle; - }); - function handleContextMenu(e, item) { e.preventDefault(); isCurrent.value = PageEnum.BASE_HOME_REDIRECT === item.path; @@ -475,7 +475,6 @@ return { ...toRefs(state), navWrap, - navRef, navScroll, route, tabsList, @@ -492,7 +491,6 @@ closeHandleSelect, scrollNext, scrollPrev, - getNavStyle, handleContextMenu, onClickOutside, getDarkTheme, @@ -552,18 +550,8 @@ } &-scroll { - overflow: hidden; white-space: nowrap; - - .tabs-card-nav { - padding-left: 0; - margin: 0; - float: left; - list-style: none; - box-sizing: border-box; - position: relative; - transition: transform 0.5s ease-in-out; - } + overflow: hidden; &-item { background: var(--color);