Files
aurora-admin/frameworks/Tabs.vue3.vue
T

88 lines
4.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="aa-tabs" :class="['type-' + type]">
<div class="aa-tabs-nav">
<div
v-for="tab in tabs" :key="tab.key"
class="aa-tabs-tab"
:class="{ 'is-active': modelValue === tab.key, 'is-disabled': tab.disabled }"
@click="choose(tab)"
>
<slot :name="'label-' + tab.key">{{ tab.label }}</slot>
<span
v-if="closable && !tab.disabled && !tab.preventClose"
class="aa-tabs-close" title="关闭"
@click.stop="remove(tab)"
>×</span>
</div>
<div v-if="addable" class="aa-tabs-add" title="新增标签" @click="$emit('tab-add')">+</div>
</div>
<div class="aa-tabs-content">
<!-- 优先渲染与当前激活标签同名的具名插槽,否则回退到默认插槽 -->
<slot :name="modelValue">
<slot />
</slot>
</div>
</div>
</template>
<script setup>
const props = defineProps({
modelValue: { type: [String, Number], default: '' }, // 当前激活标签 key(v-model)
tabs: { type: Array, required: true }, // [{ key, label, disabled?, preventClose? }]
type: { type: String, default: 'line' }, // line | card | pill
closable: { type: Boolean, default: false },
addable: { type: Boolean, default: false }
});
const emit = defineEmits(['update:modelValue', 'change', 'tab-remove', 'tab-add']);
function choose(tab) {
if (tab.disabled) return;
emit('update:modelValue', tab.key);
emit('change', tab.key);
}
function remove(tab) {
emit('tab-remove', tab.key);
}
</script>
<!-- 样式对齐 组件7.txt PageTabs 规范 -->
<style scoped>
.aa-tabs { font-family: var(--font-family, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif); color: #262626; }
.aa-tabs-nav { display: flex; align-items: flex-end; gap: 4px; position: relative; padding: 0 4px; }
.aa-tabs.type-line .aa-tabs-nav { border-bottom: 1px solid #E8ECF1; }
.aa-tabs.type-pill .aa-tabs-nav { background: #F5F7FA; border-radius: 16px; padding: 4px; gap: 4px; }
.aa-tabs-tab { position: relative; box-sizing: border-box; display: inline-flex; align-items: center; gap: 6px;
height: 40px; padding: 0 16px; cursor: pointer; font-size: 14px; line-height: 40px; color: #262626;
border: 1px solid transparent; background: none; transition: color .15s, background .15s, border-color .15s;
user-select: none; white-space: nowrap; }
.aa-tabs-tab:hover:not(.is-active):not(.is-disabled) { color: #2F54EB; }
.aa-tabs.type-line .aa-tabs-tab { border-bottom: 2px solid transparent; margin-bottom: -1px; border-radius: 0; }
.aa-tabs.type-line .aa-tabs-tab.is-active { color: #2F54EB; font-weight: 500; border-bottom-color: #2F54EB; }
.aa-tabs.type-card .aa-tabs-nav { border-bottom: 1px solid #E8ECF1; }
.aa-tabs.type-card .aa-tabs-tab { border: 1px solid #E8ECF1; border-bottom: none; border-radius: 6px 6px 0 0; background: #F5F7FA; }
.aa-tabs.type-card .aa-tabs-tab.is-active { background: #fff; color: #2F54EB; border-color: #E8ECF1; }
.aa-tabs.type-pill .aa-tabs-tab { border: none; border-radius: 14px; height: 32px; line-height: 32px; padding: 0 14px; }
.aa-tabs.type-pill .aa-tabs-tab.is-active { background: #2F54EB; color: #fff; font-weight: 500; }
.aa-tabs-tab.is-disabled { color: #BFBFBF; cursor: not-allowed; }
.aa-tabs.type-card .aa-tabs-tab.is-disabled { background: #F5F5F5; }
.aa-tabs-close { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px;
margin-left: 4px; border-radius: 50%; font-size: 12px; color: #8C8C8C; }
.aa-tabs-close:hover { background: rgba(0,0,0,0.06); color: #262626; }
.aa-tabs.type-pill .aa-tabs-close { color: rgba(255,255,255,0.85); }
.aa-tabs.type-pill .aa-tabs-close:hover { background: rgba(255,255,255,0.25); color: #fff; }
.aa-tabs-add { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
margin-left: 4px; border: 1px dashed #E8ECF1; border-radius: 6px; color: #8C8C8C; cursor: pointer; font-size: 16px; }
.aa-tabs-add:hover { color: #2F54EB; border-color: #2F54EB; }
.aa-tabs-content { padding: 16px; font-size: 14px; color: #262626; }
.aa-tabs.type-card .aa-tabs-content { border: 1px solid #E8ECF1; border-top: none; border-radius: 0 0 6px 6px; }
</style>