edu/admin/src/layout/default/components/header/multiple-tabs.vue

132 lines
4.0 KiB
Vue

<template>
<div class="app-tabs pl-4 flex bg-body">
<div class="flex-1 min-w-0">
<el-tabs
:model-value="currentTab"
:closable="tabsState.length > 1"
@tab-change="handleChange"
@tab-remove="handleRemove"
>
<template v-for="item in tabsState" :key="item.path">
<el-tab-pane :label="item.title" :name="item.path"></el-tab-pane>
</template>
</el-tabs>
</div>
<el-dropdown @command="handleCommand">
<span class="flex items-center px-3">
<icon :size="16" name="el-icon-arrow-down" />
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="closeCurrent"> 关闭当前 </el-dropdown-item>
<el-dropdown-item command="closeOther"> 关闭其他 </el-dropdown-item>
<el-dropdown-item command="closeAll"> 关闭全部 </el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<script setup lang="ts">
import { useWatchRoute } from '@/hooks/useWatchRoute'
import useTabsStore, { getRouteParams } from '@/stores/modules/multipleTabs'
const router = useRouter()
const tabsStore = useTabsStore()
const { route } = useWatchRoute((route) => {
tabsStore.addTab(route, router)
})
const currentTab = computed(() => {
return route.path
})
const tabsState = computed(() => {
return tabsStore.getTabList
})
const handleChange = (path: any) => {
const tabItem = tabsStore.tasMap[path]
router.push(getRouteParams(tabItem))
}
const handleRemove = (path: any) => {
tabsStore.removeTab(path, router)
}
const handleCommand = (command: any) => {
switch (command) {
case 'closeCurrent':
handleRemove(route.path)
break
case 'closeOther':
tabsStore.removeOtherTab(route.path)
break
case 'closeAll':
tabsStore.removeAllTab(router)
break
}
}
</script>
<style lang="scss" scoped>
.app-tabs {
@apply border-t border-br;
:deep(.el-tabs) {
height: 40px;
.el-tabs {
&__header {
margin-bottom: 0;
}
&__content {
display: none;
}
&__nav-next,
&__nav-prev {
@apply text-xl;
}
&__nav-wrap::after {
height: 0;
}
&__item {
font-weight: normal;
padding: 0 15px !important;
box-sizing: border-box;
&.is-active {
background-color: var(--el-color-primary-light-9);
&::before {
content: '';
display: inline-block;
width: 6px;
height: 6px;
background-color: var(--el-color-primary);
margin-right: 6px;
border-radius: 50%;
vertical-align: 2px;
}
&::after {
position: absolute;
content: '';
display: block;
top: 0;
height: 2px;
left: 0;
width: 100%;
background-color: var(--el-color-primary);
}
}
.is-icon-close {
color: var(--el-text-color-regular);
vertical-align: -2px;
&:hover {
color: var(--color-white);
background-color: var(--el-color-danger);
}
}
}
&__active-bar {
display: none;
}
}
}
}
</style>