-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtabspa.vue
More file actions
120 lines (110 loc) · 3.14 KB
/
Copy pathtabspa.vue
File metadata and controls
120 lines (110 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<template>
<div class="dynamic-tabs-wrapper">
<el-tabs v-model="activeTabName" type="card" class="demo-tabs">
<el-tab-pane
v-for="tab in tabDataList"
:key="tab.name"
:label="tab.label"
:name="tab.name"
>
<template #label>
<div class="custom-tab-header">
<el-icon class="tab-icon">
<component :is="tab.icon" />
</el-icon>
<span class="tab-name">{{ tab.label }}</span>
<el-badge
:value="tab.count"
:max="99"
:hidden="tab.count === 0"
class="tab-count"
/>
</div>
</template>
<KeepAlive>
<component
:is="tab.component"
v-bind="tab.props"
@data-updated="(data) => handleDataUpdate(tab.name, data)"
/>
</KeepAlive>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup>
import { ref, markRaw, KeepAlive } from "vue";
import { ElTabs, ElTabPane, ElIcon, ElBadge } from "element-plus";
import { User, Tickets, Setting } from "@element-plus/icons-vue";
// 导入子组件
import UserProfile from "./UserProfile.vue";
import OrderDetails from "./OrderDetails.vue";
import SystemSettings from "./SystemSettings.vue";
// 核心数据结构:包含 Header 信息 (icon, count) 和 Content 信息 (component, props)
const tabDataList = ref([
{
label: "用户资料",
name: "user_profile",
icon: markRaw(User), // 图标组件引用
count: 0, // 动态数据:0
component: markRaw(UserProfile),
props: { userId: 1001, defaultRole: "Admin" },
},
{
label: "待处理订单",
name: "recent_orders",
icon: markRaw(Tickets),
count: 15, // 动态数据:15 (会显示徽章)
component: markRaw(OrderDetails),
props: { itemsLimit: 10, filterStatus: "Pending" },
},
{
label: "系统配置",
name: "sys_settings",
icon: markRaw(Setting),
count: 3, // 动态数据:3
component: markRaw(SystemSettings),
props: { themeMode: "Dark", language: "zh-CN" },
},
]);
// 绑定当前激活的 Tab
const activeTabName = ref(tabDataList.value[0].name);
// 处理子组件触发的事件,用于更新 Tab Header 上的数量
const handleDataUpdate = (tabName, newData) => {
console.log(`Tab [${tabName}] 的组件触发了数据更新:`, newData);
const tabItem = tabDataList.value.find((tab) => tab.name === tabName);
if (tabItem) {
// 示例:如果子组件传递了 newCount,就更新 Tab Header 上的徽章
if (newData.newCount !== undefined) {
tabItem.count = newData.newCount;
}
}
};
</script>
<style scoped>
.dynamic-tabs-wrapper {
padding: 20px;
}
.custom-tab-header {
display: flex;
align-items: center;
}
.tab-icon {
margin-right: 5px;
font-size: 16px;
}
.tab-name {
margin-right: 15px;
}
/* 深度修改 Element Plus Badge 的样式,使其在 Tab 内居中和缩小 */
.tab-count :deep(.el-badge__content) {
top: 0;
right: -5px;
transform: scale(0.8) translate(0, 0);
transform-origin: right center;
font-size: 12px;
height: 18px;
line-height: 18px;
padding: 0 6px;
}
</style>