Merge pull request #33 from devlemoe/main

feat: TagsView自动滚动功能
This commit is contained in:
Ah jung
2021-09-15 17:11:01 +08:00
committed by GitHub

View File

@@ -30,27 +30,26 @@
</n-icon>
</span>
<div ref="navScroll" class="tabs-card-scroll">
<div ref="navRef" class="tabs-card-nav" :style="getNavStyle">
<Draggable :list="tabsList" animation="300" item-key="fullPath" class="flex">
<template #item="{ element }">
<div
class="tabs-card-scroll-item"
:class="{ 'active-item': activeKey === element.path }"
@click.stop="goPage(element)"
@contextmenu="handleContextMenu($event, element)"
<Draggable :list="tabsList" animation="300" item-key="fullPath" class="flex">
<template #item="{ element }">
<div
:id="`tag${element.fullPath.split('/').join('\/')}`"
class="tabs-card-scroll-item"
:class="{ 'active-item': activeKey === element.path }"
@click.stop="goPage(element)"
@contextmenu="handleContextMenu($event, element)"
>
<span>{{ element.meta.title }}</span>
<n-icon
size="14"
@click.stop="closeTabItem(element)"
v-if="element.path !== baseHome"
>
<span>{{ element.meta.title }}</span>
<n-icon
size="14"
@click.stop="closeTabItem(element)"
v-if="element.path != baseHome"
>
<CloseOutlined />
</n-icon>
</div>
</template>
</Draggable>
</div>
<CloseOutlined />
</n-icon>
</div>
</template>
</Draggable>
</div>
</div>
<div class="tabs-close">
@@ -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);