fix: 修改TagsView样式问题
This commit is contained in:
parent
6fff76e3f8
commit
58337f771e
@ -2,8 +2,8 @@
|
||||
<div
|
||||
class="box-border tabs-view"
|
||||
:class="{
|
||||
'tabs-view-fix': state.multiTabsSetting.fixed,
|
||||
'tabs-view-fixed-header': state.isMultiHeaderFixed,
|
||||
'tabs-view-fix': multiTabsSetting.fixed,
|
||||
'tabs-view-fixed-header': isMultiHeaderFixed,
|
||||
'tabs-view-default-background': getDarkTheme === false,
|
||||
'tabs-view-dark-background': getDarkTheme === true,
|
||||
}"
|
||||
@ -13,11 +13,11 @@
|
||||
<div
|
||||
ref="navWrap"
|
||||
class="tabs-card"
|
||||
:class="{ 'tabs-card-scrollable': state.scrollable }"
|
||||
:class="{ 'tabs-card-scrollable': scrollable }"
|
||||
>
|
||||
<span
|
||||
class="tabs-card-prev"
|
||||
:class="{ 'tabs-card-prev-hide': !state.scrollable }"
|
||||
:class="{ 'tabs-card-prev-hide': !scrollable }"
|
||||
@click="scrollPrev"
|
||||
>
|
||||
<n-icon size="16" color="#515a6e">
|
||||
@ -26,7 +26,7 @@
|
||||
</span>
|
||||
<span
|
||||
class="tabs-card-next"
|
||||
:class="{ 'tabs-card-next-hide': !state.scrollable }"
|
||||
:class="{ 'tabs-card-next-hide': !scrollable }"
|
||||
@click="scrollNext"
|
||||
>
|
||||
<n-icon size="16" color="#515a6e">
|
||||
@ -44,7 +44,7 @@
|
||||
<div
|
||||
:id="`tag${element.fullPath.split('/').join('\/')}`"
|
||||
class="tabs-card-scroll-item"
|
||||
:class="{ 'active-item': state.activeKey === element.fullPath }"
|
||||
:class="{ 'active-item': activeKey === element.fullPath }"
|
||||
@click.stop="goPage(element)"
|
||||
@contextmenu="handleContextMenu($event, element)"
|
||||
>
|
||||
@ -76,9 +76,9 @@
|
||||
</n-dropdown>
|
||||
</div>
|
||||
<n-dropdown
|
||||
:show="state.showDropdown"
|
||||
:x="state.dropdownX"
|
||||
:y="state.dropdownY"
|
||||
:show="showDropdown"
|
||||
:x="dropdownX"
|
||||
:y="dropdownY"
|
||||
@clickoutside="onClickOutside"
|
||||
placement="bottom-start"
|
||||
@select="closeHandleSelect"
|
||||
@ -88,13 +88,26 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts">
|
||||
import {
|
||||
defineComponent,
|
||||
reactive,
|
||||
computed,
|
||||
ref,
|
||||
toRefs,
|
||||
provide,
|
||||
watch,
|
||||
onMounted,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { storage } from '@/utils';
|
||||
import { StorageEnum } from '@/enums/storageEnum';
|
||||
import { useTabsViewStore } from '@/store/modules/tabsView';
|
||||
import { useAsyncRouteStore } from '@/store/modules/asyncRoute';
|
||||
import { RouteItem } from '@/store/modules/tabsView';
|
||||
import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import Draggable from 'vuedraggable';
|
||||
import { PageEnum } from '@/enums/pageEnum';
|
||||
import {
|
||||
@ -107,390 +120,432 @@ import {
|
||||
RightOutlined,
|
||||
} from '@vicons/antd';
|
||||
import { renderIcon } from '@/utils';
|
||||
// import elementResizeDetectorMaker from "element-resize-detector";
|
||||
// import elementResizeDetectorMaker from 'element-resize-detector';
|
||||
import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
|
||||
import { useProjectSettingStore } from '@/store/modules/projectSetting';
|
||||
import { useThemeVars } from 'naive-ui';
|
||||
import { useGo } from '@/hooks/web/usePage';
|
||||
import { StorageEnum } from '@/enums/storageEnum';
|
||||
const props = defineProps({
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TabsView',
|
||||
components: {
|
||||
DownOutlined,
|
||||
CloseOutlined,
|
||||
LeftOutlined,
|
||||
RightOutlined,
|
||||
Draggable,
|
||||
},
|
||||
});
|
||||
const { getDarkTheme, getAppTheme } = useDesignSetting();
|
||||
const { navMode, headerSetting, menuSetting, multiTabsSetting, isMobile } =
|
||||
useProjectSetting();
|
||||
const settingStore = useProjectSettingStore();
|
||||
props: {
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { getDarkTheme, getAppTheme } = useDesignSetting();
|
||||
const { navMode, headerSetting, menuSetting, multiTabsSetting, isMobile } =
|
||||
useProjectSetting();
|
||||
const settingStore = useProjectSettingStore();
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const tabsViewStore = useTabsViewStore();
|
||||
const asyncRouteStore = useAsyncRouteStore();
|
||||
const navScroll: any = ref(null);
|
||||
const navWrap: any = ref(null);
|
||||
const isCurrent = ref(false);
|
||||
const go = useGo();
|
||||
const message = useMessage();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const tabsViewStore = useTabsViewStore();
|
||||
const asyncRouteStore = useAsyncRouteStore();
|
||||
const navScroll: any = ref(null);
|
||||
const navWrap: any = ref(null);
|
||||
const isCurrent = ref(false);
|
||||
const go = useGo();
|
||||
|
||||
const themeVars = useThemeVars();
|
||||
const themeVars = useThemeVars();
|
||||
|
||||
const getCardColor = computed(() => {
|
||||
return themeVars.value.cardColor;
|
||||
});
|
||||
const getcardcolor = computed(() => {
|
||||
return themeVars.value.cardColor;
|
||||
});
|
||||
|
||||
const getBaseColor = computed(() => {
|
||||
return themeVars.value.textColor1;
|
||||
});
|
||||
const getbasecolor = computed(() => {
|
||||
return themeVars.value.textColor1;
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
activeKey: route.fullPath,
|
||||
scrollable: false,
|
||||
dropdownX: 0,
|
||||
dropdownY: 0,
|
||||
showDropdown: false,
|
||||
isMultiHeaderFixed: false,
|
||||
multiTabsSetting: multiTabsSetting,
|
||||
});
|
||||
const state = reactive({
|
||||
activeKey: route.fullPath,
|
||||
scrollable: false,
|
||||
dropdownX: 0,
|
||||
dropdownY: 0,
|
||||
showDropdown: false,
|
||||
isMultiHeaderFixed: false,
|
||||
multiTabsSetting: multiTabsSetting,
|
||||
});
|
||||
|
||||
// 获取简易的路由对象
|
||||
const getSimpleRoute = (route): RouteItem => {
|
||||
const { fullPath, hash, meta, name, params, path, query } = route;
|
||||
return { fullPath, hash, meta, name, params, path, query };
|
||||
};
|
||||
|
||||
const isMixMenuNoneSub = computed(() => {
|
||||
const mixMenu = settingStore.menuSetting.mixMenu;
|
||||
const currentRoute = useRoute();
|
||||
if (navMode.value != 'horizontal-mix') return true;
|
||||
return !(
|
||||
navMode.value === 'horizontal-mix' &&
|
||||
mixMenu &&
|
||||
currentRoute.meta.isRoot
|
||||
);
|
||||
});
|
||||
|
||||
//动态组装样式 菜单缩进
|
||||
const getChangeStyle = computed(() => {
|
||||
const { collapsed } = props;
|
||||
const { minMenuWidth, menuWidth }: any = menuSetting.value;
|
||||
const { fixed }: any = multiTabsSetting.value;
|
||||
let lenNum =
|
||||
navMode.value === 'horizontal' || !isMixMenuNoneSub.value
|
||||
? '0px'
|
||||
: collapsed
|
||||
? `${minMenuWidth}px`
|
||||
: `${menuWidth}px`;
|
||||
|
||||
if (isMobile.value) {
|
||||
return {
|
||||
left: '0px',
|
||||
width: '100%',
|
||||
// 获取简易的路由对象
|
||||
const getSimpleRoute = (route): RouteItem => {
|
||||
const { fullPath, hash, meta, name, params, path, query } = route;
|
||||
return { fullPath, hash, meta, name, params, path, query };
|
||||
};
|
||||
}
|
||||
return {
|
||||
left: lenNum,
|
||||
width: `calc(100% - ${!fixed ? '0px' : lenNum})`,
|
||||
};
|
||||
});
|
||||
|
||||
//tags 右侧下拉菜单
|
||||
const TabsMenuOptions = computed(() => {
|
||||
const isDisabled = tabsList.value.length <= 1;
|
||||
return [
|
||||
{
|
||||
label: '刷新当前',
|
||||
key: '1',
|
||||
icon: renderIcon(ReloadOutlined),
|
||||
},
|
||||
{
|
||||
label: `关闭当前`,
|
||||
key: '2',
|
||||
disabled: isCurrent.value || isDisabled,
|
||||
icon: renderIcon(CloseOutlined),
|
||||
},
|
||||
{
|
||||
label: '关闭其他',
|
||||
key: '3',
|
||||
disabled: isDisabled,
|
||||
icon: renderIcon(ColumnWidthOutlined),
|
||||
},
|
||||
{
|
||||
label: '关闭全部',
|
||||
key: '4',
|
||||
disabled: isDisabled,
|
||||
icon: renderIcon(MinusOutlined),
|
||||
},
|
||||
];
|
||||
});
|
||||
const isMixMenuNoneSub = computed(() => {
|
||||
const mixMenu = settingStore.menuSetting.mixMenu;
|
||||
const currentRoute = useRoute();
|
||||
if (navMode.value != 'horizontal-mix') return true;
|
||||
return !(
|
||||
navMode.value === 'horizontal-mix' &&
|
||||
mixMenu &&
|
||||
currentRoute.meta.isRoot
|
||||
);
|
||||
});
|
||||
|
||||
let cacheRoutes: RouteItem[] = [];
|
||||
const simpleRoute = getSimpleRoute(route);
|
||||
try {
|
||||
const routesStr = storage.get(StorageEnum.ZS_TABS_ROUTES) as
|
||||
| string
|
||||
| null
|
||||
| undefined;
|
||||
cacheRoutes = routesStr ? JSON.parse(routesStr) : [simpleRoute];
|
||||
} catch (e) {
|
||||
cacheRoutes = [simpleRoute];
|
||||
}
|
||||
//动态组装样式 菜单缩进
|
||||
const getChangeStyle = computed(() => {
|
||||
const { collapsed } = props;
|
||||
const { minMenuWidth, menuWidth }: any = menuSetting.value;
|
||||
const { fixed }: any = multiTabsSetting.value;
|
||||
let lenNum =
|
||||
navMode.value === 'horizontal' || !isMixMenuNoneSub.value
|
||||
? '0px'
|
||||
: collapsed
|
||||
? `${minMenuWidth}px`
|
||||
: `${menuWidth}px`;
|
||||
|
||||
// 将最新的路由信息同步到 localStorage 中
|
||||
const routes = router.getRoutes();
|
||||
cacheRoutes.forEach((cacheRoute) => {
|
||||
const route = routes.find((route) => route.path === cacheRoute.path);
|
||||
if (route) {
|
||||
cacheRoute.meta = route.meta || cacheRoute.meta;
|
||||
cacheRoute.name = (route.name || cacheRoute.name) as string;
|
||||
}
|
||||
});
|
||||
if (isMobile.value) {
|
||||
return {
|
||||
left: '0px',
|
||||
width: '100%',
|
||||
};
|
||||
}
|
||||
return {
|
||||
left: lenNum,
|
||||
width: `calc(100% - ${!fixed ? '0px' : lenNum})`,
|
||||
};
|
||||
});
|
||||
|
||||
// 初始化标签页
|
||||
tabsViewStore.initTabs(cacheRoutes);
|
||||
//tags 右侧下拉菜单
|
||||
const TabsMenuOptions = computed(() => {
|
||||
const isDisabled = tabsList.value.length <= 1;
|
||||
return [
|
||||
{
|
||||
label: '刷新当前',
|
||||
key: '1',
|
||||
icon: renderIcon(ReloadOutlined),
|
||||
},
|
||||
{
|
||||
label: `关闭当前`,
|
||||
key: '2',
|
||||
disabled: isCurrent.value || isDisabled,
|
||||
icon: renderIcon(CloseOutlined),
|
||||
},
|
||||
{
|
||||
label: '关闭其他',
|
||||
key: '3',
|
||||
disabled: isDisabled,
|
||||
icon: renderIcon(ColumnWidthOutlined),
|
||||
},
|
||||
{
|
||||
label: '关闭全部',
|
||||
key: '4',
|
||||
disabled: isDisabled,
|
||||
icon: renderIcon(MinusOutlined),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
//监听滚动条
|
||||
function onScroll(e) {
|
||||
let scrollTop =
|
||||
e.target.scrollTop ||
|
||||
document.documentElement.scrollTop ||
|
||||
window.pageYOffset ||
|
||||
document.body.scrollTop; // 滚动条偏移量
|
||||
state.isMultiHeaderFixed = !!(
|
||||
!headerSetting.value.fixed &&
|
||||
multiTabsSetting.value.fixed &&
|
||||
scrollTop >= 64
|
||||
);
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', onScroll, true);
|
||||
|
||||
// 移除缓存组件名称
|
||||
const delKeepAliveCompName = () => {
|
||||
if (route.meta.keepAlive) {
|
||||
const name = router.currentRoute.value.matched.find(
|
||||
(item) => item.name == route.name
|
||||
)?.components?.default.name;
|
||||
if (name) {
|
||||
asyncRouteStore.keepAliveComponents =
|
||||
asyncRouteStore.keepAliveComponents.filter((item) => item != name);
|
||||
let cacheRoutes: RouteItem[] = [];
|
||||
const simpleRoute = getSimpleRoute(route);
|
||||
try {
|
||||
const routesStr = storage.get(StorageEnum.ZS_TABS_ROUTES) as
|
||||
| string
|
||||
| null
|
||||
| undefined;
|
||||
cacheRoutes = routesStr ? JSON.parse(routesStr) : [simpleRoute];
|
||||
} catch (e) {
|
||||
cacheRoutes = [simpleRoute];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 标签页列表
|
||||
const tabsList: any = computed(() => tabsViewStore.tabsList);
|
||||
const whiteList: string[] = [
|
||||
PageEnum.BASE_LOGIN_NAME,
|
||||
PageEnum.REDIRECT_NAME,
|
||||
PageEnum.ERROR_PAGE_NAME,
|
||||
];
|
||||
// 将最新的路由信息同步到 localStorage 中
|
||||
const routes = router.getRoutes();
|
||||
cacheRoutes.forEach((cacheRoute) => {
|
||||
const route = routes.find((route) => route.path === cacheRoute.path);
|
||||
if (route) {
|
||||
cacheRoute.meta = route.meta || cacheRoute.meta;
|
||||
cacheRoute.name = (route.name || cacheRoute.name) as string;
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
(to) => {
|
||||
if (whiteList.includes(route.name as string)) return;
|
||||
state.activeKey = to;
|
||||
tabsViewStore.addTab(getSimpleRoute(route));
|
||||
updateNavScroll(true);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
// 初始化标签页
|
||||
tabsViewStore.initTabs(cacheRoutes);
|
||||
|
||||
// 在页面关闭或刷新之前,保存数据
|
||||
window.addEventListener('beforeunload', () => {
|
||||
storage.set(StorageEnum.ZS_TABS_ROUTES, JSON.stringify(tabsList.value));
|
||||
});
|
||||
//监听滚动条
|
||||
function onScroll(e) {
|
||||
let scrollTop =
|
||||
e.target.scrollTop ||
|
||||
document.documentElement.scrollTop ||
|
||||
window.pageYOffset ||
|
||||
document.body.scrollTop; // 滚动条偏移量
|
||||
state.isMultiHeaderFixed = !!(
|
||||
!headerSetting.value.fixed &&
|
||||
multiTabsSetting.value.fixed &&
|
||||
scrollTop >= 64
|
||||
);
|
||||
}
|
||||
|
||||
// 关闭当前页面
|
||||
const removeTab = (route) => {
|
||||
if (tabsList.value.length === 1) {
|
||||
return window['$message'].warning('这已经是最后一页,不能再关闭了!');
|
||||
}
|
||||
delKeepAliveCompName();
|
||||
tabsViewStore.closeCurrentTab(route);
|
||||
// 如果关闭的是当前页
|
||||
if (state.activeKey === route.fullPath) {
|
||||
const currentRoute = tabsList.value[Math.max(0, tabsList.value.length - 1)];
|
||||
state.activeKey = currentRoute.fullPath;
|
||||
router.push(currentRoute);
|
||||
}
|
||||
updateNavScroll();
|
||||
};
|
||||
window.addEventListener('scroll', onScroll, true);
|
||||
|
||||
// 刷新页面
|
||||
const reloadPage = () => {
|
||||
delKeepAliveCompName();
|
||||
router.push({
|
||||
path: '/redirect' + route.fullPath,
|
||||
});
|
||||
};
|
||||
|
||||
// 注入刷新页面方法
|
||||
provide('reloadPage', reloadPage);
|
||||
|
||||
// 关闭左侧
|
||||
const closeLeft = (route) => {
|
||||
tabsViewStore.closeLeftTabs(route);
|
||||
state.activeKey = route.fullPath;
|
||||
router.replace(route.fullPath);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
// 关闭右侧
|
||||
const closeRight = (route) => {
|
||||
tabsViewStore.closeRightTabs(route);
|
||||
state.activeKey = route.fullPath;
|
||||
router.replace(route.fullPath);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
// 关闭其他
|
||||
const closeOther = (route) => {
|
||||
tabsViewStore.closeOtherTabs(route);
|
||||
state.activeKey = route.fullPath;
|
||||
router.replace(route.fullPath);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
// 关闭全部
|
||||
const closeAll = () => {
|
||||
tabsViewStore.closeAllTabs();
|
||||
router.replace(PageEnum.BASE_HOME);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
//tab 操作
|
||||
const closeHandleSelect = (key) => {
|
||||
switch (key) {
|
||||
//刷新
|
||||
case '1':
|
||||
reloadPage();
|
||||
break;
|
||||
//关闭
|
||||
case '2':
|
||||
removeTab(route);
|
||||
break;
|
||||
//关闭其他
|
||||
case '3':
|
||||
closeOther(route);
|
||||
break;
|
||||
//关闭所有
|
||||
case '4':
|
||||
closeAll();
|
||||
break;
|
||||
}
|
||||
updateNavScroll();
|
||||
state.showDropdown = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @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 currentScroll = navScroll.value.scrollLeft;
|
||||
|
||||
if (!currentScroll) return;
|
||||
const scrollLeft =
|
||||
currentScroll > containerWidth ? currentScroll - containerWidth : 0;
|
||||
scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
|
||||
}
|
||||
|
||||
function scrollNext() {
|
||||
const containerWidth = navScroll.value.offsetWidth;
|
||||
const navWidth = navScroll.value.scrollWidth;
|
||||
const currentScroll = navScroll.value.scrollLeft;
|
||||
|
||||
if (navWidth - currentScroll <= containerWidth) return;
|
||||
const scrollLeft =
|
||||
navWidth - currentScroll > containerWidth * 2
|
||||
? currentScroll + containerWidth
|
||||
: navWidth - containerWidth;
|
||||
scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 (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();
|
||||
// 移除缓存组件名称
|
||||
const delKeepAliveCompName = () => {
|
||||
if (route.meta.keepAlive) {
|
||||
const name = router.currentRoute.value.matched.find(
|
||||
(item) => item.name == route.name
|
||||
)?.components?.default.name;
|
||||
if (name) {
|
||||
asyncRouteStore.keepAliveComponents =
|
||||
asyncRouteStore.keepAliveComponents.filter((item) => item != name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 标签页列表
|
||||
const tabsList: any = computed(() => tabsViewStore.tabsList);
|
||||
const whiteList: string[] = [
|
||||
PageEnum.BASE_LOGIN_NAME,
|
||||
PageEnum.REDIRECT_NAME,
|
||||
PageEnum.ERROR_PAGE_NAME,
|
||||
];
|
||||
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
(to) => {
|
||||
if (whiteList.includes(route.name as string)) return;
|
||||
state.activeKey = to;
|
||||
tabsViewStore.addTab(getSimpleRoute(route));
|
||||
updateNavScroll(true);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 在页面关闭或刷新之前,保存数据
|
||||
window.addEventListener('beforeunload', () => {
|
||||
storage.set(StorageEnum.ZS_TABS_ROUTES, JSON.stringify(tabsList.value));
|
||||
});
|
||||
|
||||
// 关闭当前页面
|
||||
const removeTab = (route) => {
|
||||
if (tabsList.value.length === 1) {
|
||||
return message.warning('这已经是最后一页,不能再关闭了!');
|
||||
}
|
||||
delKeepAliveCompName();
|
||||
tabsViewStore.closeCurrentTab(route);
|
||||
// 如果关闭的是当前页
|
||||
if (state.activeKey === route.fullPath) {
|
||||
const currentRoute =
|
||||
tabsList.value[Math.max(0, tabsList.value.length - 1)];
|
||||
state.activeKey = currentRoute.fullPath;
|
||||
router.push(currentRoute);
|
||||
}
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
// 刷新页面
|
||||
const reloadPage = () => {
|
||||
delKeepAliveCompName();
|
||||
router.push({
|
||||
path: '/redirect' + route.fullPath,
|
||||
});
|
||||
};
|
||||
|
||||
// 注入刷新页面方法
|
||||
provide('reloadPage', reloadPage);
|
||||
|
||||
// 关闭左侧
|
||||
const closeLeft = (route) => {
|
||||
tabsViewStore.closeLeftTabs(route);
|
||||
state.activeKey = route.fullPath;
|
||||
router.replace(route.fullPath);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
// 关闭右侧
|
||||
const closeRight = (route) => {
|
||||
tabsViewStore.closeRightTabs(route);
|
||||
state.activeKey = route.fullPath;
|
||||
router.replace(route.fullPath);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
// 关闭其他
|
||||
const closeOther = (route) => {
|
||||
tabsViewStore.closeOtherTabs(route);
|
||||
state.activeKey = route.fullPath;
|
||||
router.replace(route.fullPath);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
// 关闭全部
|
||||
const closeAll = () => {
|
||||
tabsViewStore.closeAllTabs();
|
||||
router.replace(PageEnum.BASE_HOME);
|
||||
updateNavScroll();
|
||||
};
|
||||
|
||||
//tab 操作
|
||||
const closeHandleSelect = (key) => {
|
||||
switch (key) {
|
||||
//刷新
|
||||
case '1':
|
||||
reloadPage();
|
||||
break;
|
||||
//关闭
|
||||
case '2':
|
||||
removeTab(route);
|
||||
break;
|
||||
//关闭其他
|
||||
case '3':
|
||||
closeOther(route);
|
||||
break;
|
||||
//关闭所有
|
||||
case '4':
|
||||
closeAll();
|
||||
break;
|
||||
}
|
||||
updateNavScroll();
|
||||
state.showDropdown = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @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 currentScroll = navScroll.value.scrollLeft;
|
||||
|
||||
if (!currentScroll) return;
|
||||
const scrollLeft =
|
||||
currentScroll > containerWidth ? currentScroll - containerWidth : 0;
|
||||
scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
|
||||
}
|
||||
|
||||
function scrollNext() {
|
||||
const containerWidth = navScroll.value.offsetWidth;
|
||||
const navWidth = navScroll.value.scrollWidth;
|
||||
const currentScroll = navScroll.value.scrollLeft;
|
||||
|
||||
if (navWidth - currentScroll <= containerWidth) return;
|
||||
const scrollLeft =
|
||||
navWidth - currentScroll > containerWidth * 2
|
||||
? currentScroll + containerWidth
|
||||
: navWidth - containerWidth;
|
||||
scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
function handleResize() {
|
||||
updateNavScroll(true);
|
||||
}
|
||||
|
||||
function handleContextMenu(e, item) {
|
||||
e.preventDefault();
|
||||
isCurrent.value = PageEnum.BASE_HOME === item.path;
|
||||
state.showDropdown = false;
|
||||
nextTick().then(() => {
|
||||
state.showDropdown = true;
|
||||
state.dropdownX = e.clientX;
|
||||
state.dropdownY = e.clientY;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
state.scrollable = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleResize() {
|
||||
updateNavScroll(true);
|
||||
}
|
||||
function onClickOutside() {
|
||||
state.showDropdown = false;
|
||||
}
|
||||
|
||||
function handleContextMenu(e, item) {
|
||||
e.preventDefault();
|
||||
isCurrent.value = PageEnum.BASE_HOME === item.path;
|
||||
state.showDropdown = false;
|
||||
nextTick().then(() => {
|
||||
state.showDropdown = true;
|
||||
state.dropdownX = e.clientX;
|
||||
state.dropdownY = e.clientY;
|
||||
});
|
||||
}
|
||||
//tags 跳转页面
|
||||
function goPage(e) {
|
||||
const { fullPath } = e;
|
||||
if (fullPath === route.fullPath) return;
|
||||
state.activeKey = fullPath;
|
||||
go(e, true);
|
||||
}
|
||||
|
||||
function onClickOutside() {
|
||||
state.showDropdown = false;
|
||||
}
|
||||
//删除tab
|
||||
function closeTabItem(e) {
|
||||
const { fullPath } = e;
|
||||
const routeInfo = tabsList.value.find(
|
||||
(item) => item.fullPath == fullPath
|
||||
);
|
||||
removeTab(routeInfo);
|
||||
}
|
||||
|
||||
//tags 跳转页面
|
||||
function goPage(e) {
|
||||
const { fullPath } = e;
|
||||
if (fullPath === route.fullPath) return;
|
||||
state.activeKey = fullPath;
|
||||
go(e, true);
|
||||
}
|
||||
onMounted(() => {
|
||||
// onElementResize();
|
||||
});
|
||||
|
||||
//删除tab
|
||||
function closeTabItem(e) {
|
||||
const { fullPath } = e;
|
||||
const routeInfo = tabsList.value.find((item) => item.fullPath == fullPath);
|
||||
removeTab(routeInfo);
|
||||
}
|
||||
// function onElementResize() {
|
||||
// let observer;
|
||||
// observer = elementResizeDetectorMaker();
|
||||
// observer.listenTo(navWrap.value, handleResize);
|
||||
// }
|
||||
|
||||
onMounted(() => {
|
||||
// onElementResize();
|
||||
return {
|
||||
...toRefs(state),
|
||||
navWrap,
|
||||
navScroll,
|
||||
route,
|
||||
tabsList,
|
||||
goPage,
|
||||
closeTabItem,
|
||||
closeLeft,
|
||||
closeRight,
|
||||
closeOther,
|
||||
closeAll,
|
||||
reloadPage,
|
||||
getChangeStyle,
|
||||
TabsMenuOptions,
|
||||
closeHandleSelect,
|
||||
scrollNext,
|
||||
scrollPrev,
|
||||
handleContextMenu,
|
||||
onClickOutside,
|
||||
getDarkTheme,
|
||||
getAppTheme,
|
||||
getcardcolor,
|
||||
getbasecolor,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
// function onElementResize() {
|
||||
// let observer;
|
||||
// observer = elementResizeDetectorMaker();
|
||||
// observer.listenTo(navWrap.value, handleResize);
|
||||
// }
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user