<template>
|
<div class="tabs-box">
|
<div class="tabs-menu">
|
<el-tabs v-model="tabsMenuValue" type="card" @tab-click="tabClick" @tab-remove="tabRemove">
|
<el-tab-pane v-for="item in tabsMenuList" :key="item.path" :label="item.title" :name="item.path" :closable="item.close">
|
<template #label>
|
<el-icon v-if="item.icon && tabsIcon" class="tabs-icon">
|
<component :is="item.icon"></component>
|
</el-icon>
|
{{ getMenuTitle(item) }}
|
</template>
|
</el-tab-pane>
|
</el-tabs>
|
<MoreButton />
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import Sortable from "sortablejs";
|
import { ref, computed, watch, onMounted } from "vue";
|
import { useRoute, useRouter } from "vue-router";
|
import { useGlobalStore } from "@/stores/modules/global";
|
import { useTabsStore } from "@/stores/modules/tabs";
|
import { useAuthStore } from "@/stores/modules/auth";
|
import { TabsPaneContext, TabPaneName } from "element-plus";
|
import MoreButton from "./components/MoreButton.vue";
|
|
const route = useRoute();
|
const router = useRouter();
|
const tabStore = useTabsStore();
|
const authStore = useAuthStore();
|
const globalStore = useGlobalStore();
|
const currentLanguage = computed(() => globalStore.language);
|
const tabsMenuValue = ref(route.fullPath);
|
const tabsMenuList = computed(() => tabStore.tabsMenuList);
|
console.log(tabsMenuList);
|
const tabsIcon = computed(() => globalStore.tabsIcon);
|
const getMenuTitle = (subItem: Menu.MenuOptions) => {
|
// 如果是英文且存在英文标题,则使用英文标题
|
if (currentLanguage.value === "en" && subItem.entitle) {
|
return subItem.entitle;
|
}
|
// 否则使用默认标题
|
return subItem.title;
|
};
|
onMounted(() => {
|
tabsDrop();
|
initTabs();
|
});
|
|
// 监听路由的变化(防止浏览器后退/前进不变化 tabsMenuValue)
|
watch(
|
() => route.fullPath,
|
() => {
|
if (route.meta.isFull) return;
|
tabsMenuValue.value = route.fullPath;
|
const tabsParams = {
|
icon: route.meta.icon as string,
|
title: route.meta.title as string,
|
entitle: route.meta.entitle as string,
|
path: route.fullPath,
|
name: route.name as string,
|
close: !route.meta.isAffix,
|
isKeepAlive: route.meta.isKeepAlive as boolean
|
};
|
tabStore.addTabs(tabsParams);
|
},
|
{ immediate: true }
|
);
|
|
// 初始化需要固定的 tabs
|
const initTabs = () => {
|
authStore.flatMenuListGet.forEach(item => {
|
if (item.meta.isAffix && !item.meta.isHide && !item.meta.isFull) {
|
const tabsParams = {
|
icon: item.meta.icon,
|
title: item.meta.title,
|
entitle: item.meta.entitle,
|
path: item.path,
|
name: item.name,
|
close: !item.meta.isAffix,
|
isKeepAlive: item.meta.isKeepAlive
|
};
|
tabStore.addTabs(tabsParams);
|
}
|
});
|
};
|
|
// tabs 拖拽排序
|
const tabsDrop = () => {
|
Sortable.create(document.querySelector(".el-tabs__nav") as HTMLElement, {
|
draggable: ".el-tabs__item",
|
animation: 300,
|
onEnd({ newIndex, oldIndex }) {
|
const tabsList = [...tabStore.tabsMenuList];
|
const currRow = tabsList.splice(oldIndex as number, 1)[0];
|
tabsList.splice(newIndex as number, 0, currRow);
|
tabStore.setTabs(tabsList);
|
}
|
});
|
};
|
|
// Tab Click
|
const tabClick = (tabItem: TabsPaneContext) => {
|
const fullPath = tabItem.props.name as string;
|
router.push(fullPath);
|
};
|
|
// Remove Tab
|
const tabRemove = (fullPath: TabPaneName) => {
|
tabStore.removeTabs(fullPath as string, fullPath == route.fullPath);
|
};
|
</script>
|
|
<style scoped lang="scss">
|
@import "./index";
|
</style>
|