You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
shop-admin/src/layouts/components/tabs.vue

162 lines
6.1 KiB

<template>
<div class="layout-tabs">
<el-tabs :modelValue="activeTab" type="card" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane v-for="(item, index) in tabList" :key="index" :name="item.name">
<template #label>
<XIcon class="tab-icon" :name="item.meta.icon" />
<span>{{ item.meta.title }}</span>
<XIcon
v-if="tabList.length > 1"
class="tab-close"
name="close-fill"
@click.stop="handleCloseTab(index)"
/>
</template>
</el-tab-pane>
</el-tabs>
<div class="operation">
<el-dropdown trigger="hover" @command="handleCommand">
<span class="el-dropdown-link">
<XIcon name="apps-fill" />
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="all">关闭全部</el-dropdown-item>
<el-dropdown-item command="other"></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<script setup>
const router = useRouter();
const store = useStore();
const activeTab = computed(() => store.state.layout.activeTab);
const tabList = computed(() => store.state.layout.tabList);
// 标签列表变化时如果激活标签不存在则跳转到第一个标签
watch(
() => unref(tabList),
(value) => {
if (!unref(activeTab) || value.findIndex((item) => item.name === unref(activeTab)) === -1) {
router.push({ name: value[0].name });
}
},
{ immediate: true, deep: true }
);
const handleCloseTab = (index) => {
store.commit('layout/closeTab', {
index,
});
};
const handleClick = (tab) => {
router.push(unref(tabList)[tab.index].fullPath);
};
const handleCommand = (command) => {
switch (command) {
case 'all':
store.commit('layout/closeTab', {});
break;
case 'other':
store.commit('layout/closeTab', {
index: unref(tabList).findIndex((item) => item.name === unref(activeTab)),
reverse: true,
});
break;
}
};
</script>
<style lang="less" scoped>
.layout-tabs {
width: 100%;
height: @layout-tabs-height;
padding: 0 @layout-space-large;
display: flex;
align-items: flex-end;
justify-content: space-between;
overflow: hidden;
box-shadow: fade(@layout-header-fc, 15%) 0 1px 5px;
background-color: @layout-header-bgc;
color: @layout-header-fc;
.el-tabs {
height: 80%;
width: 100%;
flex-shrink: 1;
overflow: hidden;
:deep(.el-tabs__header) {
margin: 0;
height: 100%;
.el-tabs__nav-wrap {
height: 100%;
margin-bottom: 0;
> * {
height: 100%;
display: flex;
align-items: center;
}
.el-tabs__nav-scroll {
.el-tabs__nav {
height: 100%;
border: none;
padding: 0 @layout-space-large;
display: flex;
.el-tabs__item {
height: 100%;
min-width: 100px;
margin-right: -8px;
display: flex;
align-items: center;
justify-content: center;
border: none;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
mask-image: url('~/layouts/tabs-bgp.png');
-webkit-mask-image: url('~/layouts/tabs-bgp.png');
mask-size: 100% 100%;
-webkit-mask-size: 100% 100%;
&:hover {
background-color: @color-white-dark;
.tab-close {
width: 20px;
}
}
&.is-active {
background-color: @color-primary-white;
.tab-close {
width: 20px;
}
}
.tab-icon {
margin-right: @layout-space-small;
}
.tab-close {
margin-left: @layout-space-small;
border-radius: 50px;
display: inline-block;
width: 0;
overflow: hidden;
transition: width 0.3s;
&:hover {
color: var(--el-color-danger);
}
}
}
}
}
}
}
}
.operation {
height: 80%;
margin-left: @layout-space;
display: flex;
align-items: center;
&:hover {
transform: rotate(90deg);
}
}
}
</style>