@mc-markets/ui 1.0.64 → 1.0.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/components/Alert/Alert.vue.d.ts +8 -0
  2. package/dist/components/Alert/Alert.vue.d.ts.map +1 -0
  3. package/dist/components/Banner/Banner.vue.d.ts +38 -0
  4. package/dist/components/Banner/Banner.vue.d.ts.map +1 -0
  5. package/dist/components/Button/Button.vue.d.ts +8 -0
  6. package/dist/components/Button/Button.vue.d.ts.map +1 -0
  7. package/dist/components/Card/Card.vue.d.ts +8 -0
  8. package/dist/components/Card/Card.vue.d.ts.map +1 -0
  9. package/dist/components/DatePicker/DatePicker.vue.d.ts +13 -0
  10. package/dist/components/DatePicker/DatePicker.vue.d.ts.map +1 -0
  11. package/dist/components/Dialog/Dialog.vue.d.ts +30 -0
  12. package/dist/components/Dialog/Dialog.vue.d.ts.map +1 -0
  13. package/dist/components/Empty/Empty.vue.d.ts +11 -0
  14. package/dist/components/Empty/Empty.vue.d.ts.map +1 -0
  15. package/dist/components/Form/Form.vue.d.ts +8 -0
  16. package/dist/components/Form/Form.vue.d.ts.map +1 -0
  17. package/dist/components/FormItem/FormItem.vue.d.ts +8 -0
  18. package/dist/components/FormItem/FormItem.vue.d.ts.map +1 -0
  19. package/dist/components/Icon/Icon.vue.d.ts +30 -0
  20. package/dist/components/Icon/Icon.vue.d.ts.map +1 -0
  21. package/dist/components/Input/Input.vue.d.ts +8 -0
  22. package/dist/components/Input/Input.vue.d.ts.map +1 -0
  23. package/dist/components/Notification/Notification.vue.d.ts +8 -0
  24. package/dist/components/Notification/Notification.vue.d.ts.map +1 -0
  25. package/dist/components/Option/Option.vue.d.ts +8 -0
  26. package/dist/components/Option/Option.vue.d.ts.map +1 -0
  27. package/dist/components/OptionGroup/OptionGroup.vue.d.ts +8 -0
  28. package/dist/components/OptionGroup/OptionGroup.vue.d.ts.map +1 -0
  29. package/dist/components/Pagination/Pagination.vue.d.ts +8 -0
  30. package/dist/components/Pagination/Pagination.vue.d.ts.map +1 -0
  31. package/dist/components/Radio/Radio.vue.d.ts +13 -0
  32. package/dist/components/Radio/Radio.vue.d.ts.map +1 -0
  33. package/dist/components/RadioButton/RadioButton.vue.d.ts +13 -0
  34. package/dist/components/RadioButton/RadioButton.vue.d.ts.map +1 -0
  35. package/dist/components/RadioGroup/RadioGroup.vue.d.ts +13 -0
  36. package/dist/components/RadioGroup/RadioGroup.vue.d.ts.map +1 -0
  37. package/dist/components/Select/Select.vue.d.ts +8 -0
  38. package/dist/components/Select/Select.vue.d.ts.map +1 -0
  39. package/dist/components/Switch/Switch.vue.d.ts +13 -0
  40. package/dist/components/Switch/Switch.vue.d.ts.map +1 -0
  41. package/dist/components/Table/Table.vue.d.ts +8 -0
  42. package/dist/components/Table/Table.vue.d.ts.map +1 -0
  43. package/dist/components/Table/TableColumn.vue.d.ts +8 -0
  44. package/dist/components/Table/TableColumn.vue.d.ts.map +1 -0
  45. package/dist/components/Tabs/TabPane.vue.d.ts +23 -0
  46. package/dist/components/Tabs/TabPane.vue.d.ts.map +1 -0
  47. package/dist/components/Tabs/Tabs.vue.d.ts +31 -0
  48. package/dist/components/Tabs/Tabs.vue.d.ts.map +1 -0
  49. package/dist/components/Tag/Tag.vue.d.ts +8 -0
  50. package/dist/components/Tag/Tag.vue.d.ts.map +1 -0
  51. package/dist/components/Tooltip/Tooltip.vue.d.ts +13 -0
  52. package/dist/components/Tooltip/Tooltip.vue.d.ts.map +1 -0
  53. package/dist/hooks/useClassName.d.ts +8 -0
  54. package/dist/hooks/useClassName.d.ts.map +1 -0
  55. package/dist/index.cjs +2 -0
  56. package/dist/index.cjs.map +1 -0
  57. package/dist/index.d.ts +76 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.mjs +1136 -0
  60. package/dist/index.mjs.map +1 -0
  61. package/dist/style.css +1 -0
  62. package/dist/styles/font/iconfont.d.ts +1 -0
  63. package/dist/styles/font/iconfont.d.ts.map +1 -0
  64. package/dist/utils/classNames.d.ts +3 -0
  65. package/dist/utils/classNames.d.ts.map +1 -0
  66. package/dist/utils/styleUtils.d.ts +31 -0
  67. package/dist/utils/styleUtils.d.ts.map +1 -0
  68. package/package.json +19 -18
  69. package/packages/components/Alert/Alert.vue +13 -0
  70. package/packages/components/Banner/Banner.vue +299 -0
  71. package/packages/components/Button/Button.vue +18 -0
  72. package/packages/components/Card/Card.vue +20 -0
  73. package/packages/components/DatePicker/DatePicker.vue +71 -0
  74. package/packages/components/Dialog/Dialog.vue +102 -0
  75. package/packages/components/Empty/Empty.vue +74 -0
  76. package/packages/components/Form/Form.vue +17 -0
  77. package/packages/components/FormItem/FormItem.vue +20 -0
  78. package/packages/components/Icon/Icon.vue +210 -0
  79. package/packages/components/Input/Input.vue +25 -0
  80. package/packages/components/Notification/Notification.vue +13 -0
  81. package/packages/components/Option/Option.vue +13 -0
  82. package/packages/components/OptionGroup/OptionGroup.vue +13 -0
  83. package/packages/components/Pagination/Pagination.vue +23 -0
  84. package/packages/components/Radio/Radio.vue +130 -0
  85. package/packages/components/RadioButton/RadioButton.vue +110 -0
  86. package/packages/components/RadioGroup/RadioGroup.vue +155 -0
  87. package/packages/components/Select/Select.vue +22 -0
  88. package/packages/components/Switch/Switch.vue +134 -0
  89. package/packages/components/Table/Table.vue +17 -0
  90. package/packages/components/Table/TableColumn.vue +20 -0
  91. package/packages/components/Tabs/TabPane.vue +98 -0
  92. package/packages/components/Tabs/Tabs.vue +414 -0
  93. package/packages/components/Tag/Tag.vue +61 -0
  94. package/packages/components/Tooltip/Tooltip.vue +58 -0
  95. package/packages/hooks/useClassName.js +23 -0
  96. package/packages/styles/README.md +129 -0
  97. package/packages/styles/components/override.scss +234 -0
  98. package/packages/styles/index.scss +76 -209
  99. package/packages/utils/classNames.js +23 -0
  100. package/packages/utils/styleUtils.js +105 -0
  101. package/dist/index.js +0 -19255
  102. package/dist/index.js.css +0 -1
  103. package/packages/styles/components/input.scss +0 -3
@@ -0,0 +1,134 @@
1
+ <template>
2
+ <el-switch v-bind="mergedAttrs" :popper-class="popperClass" class="m-switch">
3
+ <template v-for="(_, name) in $slots" :key="name" #[name]>
4
+ <slot :name="name" />
5
+ </template>
6
+ </el-switch>
7
+ </template>
8
+
9
+ <script setup>
10
+ import { useClassName } from "@packages/hooks/useClassName.js"
11
+
12
+ defineOptions({
13
+ name: 'MSwitch'
14
+ })
15
+
16
+ // 定义props
17
+ const props = defineProps({
18
+ popperClass: {
19
+ type: String,
20
+ default: ''
21
+ }
22
+ })
23
+
24
+ // 使用类名 Hook
25
+ const { mergedAttrs, className: popperClass } = useClassName('mc-switch-popper')
26
+ </script>
27
+
28
+ <style lang="scss">
29
+ // Switch popper-class 样式
30
+ // .mc-switch-popper {
31
+ // 自定义开关样式可以在这里添加
32
+ // }
33
+
34
+ // 自定义主题示例
35
+ .mc-switch-custom {
36
+ .el-switch__core {
37
+ background: linear-gradient(45deg, #667eea, #764ba2);
38
+ border-color: #667eea;
39
+
40
+ &:after {
41
+ background: white;
42
+ }
43
+ }
44
+
45
+ &.is-checked .el-switch__core {
46
+ background: linear-gradient(45deg, #4c63d2, #5d3a7e);
47
+ border-color: #4c63d2;
48
+ }
49
+ }
50
+
51
+ .mc-switch-success {
52
+ .el-switch__core {
53
+ background-color: #67c23a;
54
+ border-color: #67c23a;
55
+
56
+ &:after {
57
+ background: white;
58
+ }
59
+ }
60
+
61
+ &.is-checked .el-switch__core {
62
+ background-color: #529b2e;
63
+ border-color: #529b2e;
64
+ }
65
+ }
66
+
67
+ .mc-switch-warning {
68
+ .el-switch__core {
69
+ background-color: #e6a23c;
70
+ border-color: #e6a23c;
71
+
72
+ &:after {
73
+ background: white;
74
+ }
75
+ }
76
+
77
+ &.is-checked .el-switch__core {
78
+ background-color: #c8951f;
79
+ border-color: #c8951f;
80
+ }
81
+ }
82
+
83
+ .mc-switch-danger {
84
+ .el-switch__core {
85
+ background-color: #f56c6c;
86
+ border-color: #f56c6c;
87
+
88
+ &:after {
89
+ background: white;
90
+ }
91
+ }
92
+
93
+ &.is-checked .el-switch__core {
94
+ background-color: #f24545;
95
+ border-color: #f24545;
96
+ }
97
+ }
98
+
99
+ // 特殊样式变体
100
+ .mc-switch-gradient {
101
+ .el-switch__core {
102
+ background: linear-gradient(90deg, #ff6b6b, #4ecdc4);
103
+ border: none;
104
+
105
+ &:after {
106
+ background: white;
107
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
108
+ }
109
+ }
110
+
111
+ &.is-checked .el-switch__core {
112
+ background: linear-gradient(90deg, #4ecdc4, #45b7d1);
113
+ }
114
+ }
115
+
116
+ .mc-switch-neon {
117
+ .el-switch__core {
118
+ background-color: #1a1a1a;
119
+ border: 2px solid #00ffff;
120
+ box-shadow: 0 0 10px #00ffff;
121
+
122
+ &:after {
123
+ background: #00ffff;
124
+ box-shadow: 0 0 5px #00ffff;
125
+ }
126
+ }
127
+
128
+ &.is-checked .el-switch__core {
129
+ background-color: #00ffff;
130
+ border-color: #00ffff;
131
+ box-shadow: 0 0 15px #00ffff;
132
+ }
133
+ }
134
+ </style>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <el-table v-bind="$attrs">
3
+ <template v-for="(_, name) in $slots" :key="name" #[name]>
4
+ <slot :name="name" />
5
+ </template>
6
+ </el-table>
7
+ </template>
8
+
9
+ <script setup>
10
+ defineOptions({
11
+ name: "MTable",
12
+ });
13
+ </script>
14
+ <style lang="scss">
15
+ // Table 组件样式 - 无边框设计
16
+
17
+ </style>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <el-table-column v-bind="$attrs" class="m-table-column">
3
+ <template v-for="(_, name) in $slots" :key="name" #[name]>
4
+ <slot :name="name" />
5
+ </template>
6
+ </el-table-column>
7
+ </template>
8
+
9
+ <script setup>
10
+ defineOptions({
11
+ name: "MTableColumn",
12
+ });
13
+ </script>
14
+
15
+ <style lang="scss">
16
+ // TableColumn 组件样式
17
+ .m-table-column.el-table-column {
18
+ // 继承父级 Table 组件的样式
19
+ }
20
+ </style>
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <div
3
+ v-show="active"
4
+ class="m-tab-pane"
5
+ :class="{
6
+ 'm-tab-pane--active': active,
7
+ 'm-tab-pane--disabled': disabled
8
+ }"
9
+ >
10
+ <slot />
11
+ </div>
12
+ </template>
13
+
14
+ <script setup>
15
+ import { inject, computed, onMounted, onUnmounted, useSlots } from 'vue'
16
+
17
+ // 定义 props
18
+ const props = defineProps({
19
+ // 选项卡标题
20
+ label: {
21
+ type: String,
22
+ default: ''
23
+ },
24
+ // 是否禁用
25
+ disabled: {
26
+ type: Boolean,
27
+ default: false
28
+ },
29
+ // 选项卡名称,用于标识
30
+ name: {
31
+ type: [String, Number],
32
+ default: ''
33
+ },
34
+ // 是否可关闭
35
+ closable: {
36
+ type: Boolean,
37
+ default: false
38
+ },
39
+ // 是否延迟渲染
40
+ lazy: {
41
+ type: Boolean,
42
+ default: false
43
+ }
44
+ })
45
+
46
+ // 获取插槽
47
+ const slots = useSlots()
48
+
49
+ // 注入父组件上下文
50
+ const tabsContext = inject('tabsContext')
51
+
52
+ // 计算是否激活
53
+ const active = computed(() => {
54
+ if (!tabsContext) return false
55
+ return tabsContext.activeName === (props.name || tabsContext.tabIndex)
56
+ })
57
+
58
+ // 组件挂载时注册到父组件
59
+ onMounted(() => {
60
+ if (tabsContext) {
61
+ const tabData = {
62
+ name: props.name,
63
+ label: props.label,
64
+ disabled: props.disabled,
65
+ closable: props.closable,
66
+ $slots: slots
67
+ }
68
+ tabsContext.registerTab(tabData)
69
+ }
70
+ })
71
+
72
+ // 组件卸载时从父组件中移除
73
+ onUnmounted(() => {
74
+ if (tabsContext) {
75
+ tabsContext.unregisterTab(props.name)
76
+ }
77
+ })
78
+
79
+ // 定义组件名称
80
+ defineOptions({
81
+ name: 'MTabPane'
82
+ })
83
+ </script>
84
+
85
+ <style scoped lang="scss">
86
+ .m-tab-pane {
87
+ display: none;
88
+
89
+ &--active {
90
+ display: block;
91
+ }
92
+
93
+ &--disabled {
94
+ opacity: 0.6;
95
+ pointer-events: none;
96
+ }
97
+ }
98
+ </style>
@@ -0,0 +1,414 @@
1
+ <template>
2
+ <div class="m-tabs" :class="[`m-tabs--${type}`, `m-tabs--${tabPosition}`]">
3
+ <div class="m-tabs__header">
4
+ <div class="m-tabs__nav">
5
+ <div
6
+ v-for="(tab, index) in tabs"
7
+ :key="tab.name || index"
8
+ :class="[
9
+ 'm-tabs__item',
10
+ {
11
+ 'm-tabs__item--active': activeName === (tab.name || index),
12
+ 'm-tabs__item--disabled': tab.disabled,
13
+ 'm-tabs__item--closable': tab.closable
14
+ }
15
+ ]"
16
+ @click="handleTabClick(tab, index)"
17
+ >
18
+ <span class="m-tabs__item-text">
19
+ <slot v-if="tab.$slots?.label" :name="`tab-${tab.name || index}`" />
20
+ <span v-else>{{ tab.label }}</span>
21
+ </span>
22
+ <span
23
+ v-if="tab.closable"
24
+ class="m-tabs__item-close"
25
+ @click.stop="handleTabClose(tab, index)"
26
+ >
27
+ <m-icon name="lucide-x" :size="12" />
28
+ </span>
29
+ </div>
30
+
31
+ <!-- 添加按钮 -->
32
+ <div
33
+ v-if="addable || editable"
34
+ class="m-tabs__item m-tabs__item--add"
35
+ @click="handleTabAdd"
36
+ >
37
+ <m-icon name="plus" :size="12" />
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <div class="m-tabs__content">
43
+ <slot />
44
+ </div>
45
+ </div>
46
+ </template>
47
+
48
+ <script setup>
49
+ import { ref, provide, computed, useSlots, watch, nextTick } from 'vue'
50
+ import MIcon from '../Icon/Icon.vue'
51
+
52
+ // 定义 props
53
+ const props = defineProps({
54
+ // 当前激活的标签页
55
+ modelValue: {
56
+ type: [String, Number],
57
+ default: ''
58
+ },
59
+ // 标签页类型
60
+ type: {
61
+ type: String,
62
+ default: '',
63
+ validator: (value) => ['', 'card', 'border-card'].includes(value)
64
+ },
65
+ // 标签位置
66
+ tabPosition: {
67
+ type: String,
68
+ default: 'top',
69
+ validator: (value) => ['top', 'right', 'bottom', 'left'].includes(value)
70
+ },
71
+ // 是否可关闭
72
+ closable: {
73
+ type: Boolean,
74
+ default: false
75
+ },
76
+ // 是否可添加
77
+ addable: {
78
+ type: Boolean,
79
+ default: false
80
+ },
81
+ // 是否可编辑(同时可添加和关闭)
82
+ editable: {
83
+ type: Boolean,
84
+ default: false
85
+ },
86
+ // 标签宽度是否自撑开
87
+ stretch: {
88
+ type: Boolean,
89
+ default: false
90
+ },
91
+ // 切换前的钩子函数
92
+ beforeLeave: {
93
+ type: Function,
94
+ default: null
95
+ }
96
+ })
97
+
98
+ // 定义 emits
99
+ const emit = defineEmits(['update:modelValue', 'tab-click', 'tab-change', 'tab-remove', 'tab-add', 'edit'])
100
+
101
+ // 获取插槽
102
+ const slots = useSlots()
103
+
104
+ // 响应式数据
105
+ const tabs = ref([])
106
+ const activeName = ref(props.modelValue)
107
+
108
+ // 监听 modelValue 变化
109
+ watch(() => props.modelValue, (newVal) => {
110
+ activeName.value = newVal
111
+ })
112
+
113
+ // 监听 activeName 变化
114
+ watch(activeName, (newVal) => {
115
+ emit('update:modelValue', newVal)
116
+ emit('tab-change', newVal)
117
+ })
118
+
119
+ // 提供上下文给子组件
120
+ provide('tabsContext', {
121
+ registerTab: (tab) => {
122
+ const index = tabs.value.findIndex(t => t.name === tab.name)
123
+ if (index >= 0) {
124
+ tabs.value[index] = tab
125
+ } else {
126
+ tabs.value.push(tab)
127
+ }
128
+
129
+ // 如果没有指定 activeName,默认选中第一个
130
+ if (!activeName.value && tabs.value.length > 0) {
131
+ activeName.value = tabs.value[0].name || 0
132
+ }
133
+ },
134
+ unregisterTab: (name) => {
135
+ const index = tabs.value.findIndex(tab => tab.name === name)
136
+ if (index >= 0) {
137
+ tabs.value.splice(index, 1)
138
+ }
139
+ }
140
+ })
141
+
142
+ // 处理标签点击
143
+ const handleTabClick = async (tab, index) => {
144
+ if (tab.disabled) return
145
+
146
+ const tabName = tab.name || index
147
+
148
+ // 如果点击的是当前激活的标签,直接返回
149
+ if (activeName.value === tabName) return
150
+
151
+ // 执行 beforeLeave 钩子
152
+ if (props.beforeLeave) {
153
+ try {
154
+ const result = await props.beforeLeave(activeName.value, tabName)
155
+ if (result === false) return
156
+ } catch (error) {
157
+ return
158
+ }
159
+ }
160
+
161
+ activeName.value = tabName
162
+ emit('tab-click', { name: tabName, index, disabled: tab.disabled })
163
+ }
164
+
165
+ // 处理标签关闭
166
+ const handleTabClose = (tab, index) => {
167
+ const tabName = tab.name || index
168
+ emit('tab-remove', tabName)
169
+ emit('edit', tabName, 'remove')
170
+ }
171
+
172
+ // 处理添加标签
173
+ const handleTabAdd = () => {
174
+ emit('tab-add')
175
+ emit('edit', '', 'add')
176
+ }
177
+
178
+ // 暴露方法给父组件
179
+ defineExpose({
180
+ activeName: computed(() => activeName.value)
181
+ })
182
+ </script>
183
+
184
+ <style scoped lang="scss">
185
+ .m-tabs {
186
+ display: flex;
187
+ flex-direction: column;
188
+
189
+ &--left {
190
+ flex-direction: row;
191
+ }
192
+
193
+ &--right {
194
+ flex-direction: row-reverse;
195
+ }
196
+
197
+ &--bottom {
198
+ flex-direction: column-reverse;
199
+ }
200
+
201
+ &__header {
202
+ flex-shrink: 0;
203
+ }
204
+
205
+ &__nav {
206
+ display: flex;
207
+ border-bottom: 1px solid var(--el-border-color);
208
+ position: relative;
209
+
210
+ .m-tabs--card &,
211
+ .m-tabs--border-card & {
212
+ border-bottom: none;
213
+ }
214
+
215
+ .m-tabs--left &,
216
+ .m-tabs--right & {
217
+ flex-direction: column;
218
+ border-bottom: none;
219
+ border-right: 1px solid var(--el-border-color);
220
+ width: 120px;
221
+ }
222
+
223
+ .m-tabs--right & {
224
+ border-right: none;
225
+ border-left: 1px solid var(--el-border-color);
226
+ }
227
+ }
228
+
229
+ &__item {
230
+ display: flex;
231
+ align-items: center;
232
+ padding: 8px 16px;
233
+ cursor: pointer;
234
+ border: 1px solid transparent;
235
+ border-bottom: none;
236
+ background: transparent;
237
+ color: var(--el-text-color-regular);
238
+ font-size: 14px;
239
+ transition: all 0.3s ease;
240
+ position: relative;
241
+ flex-shrink: 0;
242
+
243
+ &:hover {
244
+ color: var(--el-color-primary);
245
+ }
246
+
247
+ &--active {
248
+ color: var(--el-color-primary);
249
+ border-color: var(--el-border-color);
250
+ border-bottom-color: var(--el-bg-color);
251
+ background: var(--el-bg-color);
252
+
253
+ &::after {
254
+ content: '';
255
+ position: absolute;
256
+ bottom: -1px;
257
+ left: 0;
258
+ right: 0;
259
+ height: 2px;
260
+ background: var(--el-color-primary);
261
+ }
262
+ }
263
+
264
+ &--disabled {
265
+ color: var(--el-text-color-disabled);
266
+ cursor: not-allowed;
267
+
268
+ &:hover {
269
+ color: var(--el-text-color-disabled);
270
+ }
271
+ }
272
+
273
+ &--closable {
274
+ padding-right: 24px;
275
+ }
276
+
277
+ &--add {
278
+ padding: 8px 12px;
279
+ border: 1px dashed var(--el-border-color);
280
+ color: var(--el-text-color-regular);
281
+
282
+ &:hover {
283
+ color: var(--el-color-primary);
284
+ border-color: var(--el-color-primary);
285
+ }
286
+ }
287
+
288
+ // 卡片风格
289
+ .m-tabs--card & {
290
+ border: 1px solid var(--el-border-color);
291
+ border-bottom: none;
292
+ margin-right: 2px;
293
+
294
+ &--active {
295
+ border-bottom-color: var(--el-bg-color);
296
+ background: var(--el-bg-color);
297
+
298
+ &::after {
299
+ display: none;
300
+ }
301
+ }
302
+ }
303
+
304
+ // 边框卡片风格
305
+ .m-tabs--border-card & {
306
+ border: 1px solid var(--el-border-color);
307
+ border-bottom: none;
308
+ margin-right: -1px;
309
+ background: var(--el-fill-color-light);
310
+
311
+ &--active {
312
+ background: var(--el-bg-color);
313
+ border-bottom-color: var(--el-bg-color);
314
+
315
+ &::after {
316
+ display: none;
317
+ }
318
+ }
319
+ }
320
+
321
+ // 左侧和右侧位置
322
+ .m-tabs--left &,
323
+ .m-tabs--right & {
324
+ border-bottom: 1px solid var(--el-border-color);
325
+ border-right: none;
326
+
327
+ &--active {
328
+ border-bottom-color: var(--el-border-color);
329
+ border-right-color: var(--el-bg-color);
330
+
331
+ &::after {
332
+ display: none;
333
+ }
334
+ }
335
+ }
336
+
337
+ .m-tabs--right & {
338
+ border-bottom: 1px solid var(--el-border-color);
339
+ border-left: none;
340
+
341
+ &--active {
342
+ border-bottom-color: var(--el-border-color);
343
+ border-left-color: var(--el-bg-color);
344
+ }
345
+ }
346
+ }
347
+
348
+ &__item-text {
349
+ flex: 1;
350
+ white-space: nowrap;
351
+ overflow: hidden;
352
+ text-overflow: ellipsis;
353
+ }
354
+
355
+ &__item-close {
356
+ position: absolute;
357
+ right: 8px;
358
+ top: 50%;
359
+ transform: translateY(-50%);
360
+ display: flex;
361
+ align-items: center;
362
+ justify-content: center;
363
+ width: 16px;
364
+ height: 16px;
365
+ border-radius: 50%;
366
+ transition: background-color 0.2s ease;
367
+
368
+ &:hover {
369
+ background-color: var(--el-fill-color);
370
+ }
371
+ }
372
+
373
+ &__content {
374
+ flex: 1;
375
+ padding: 16px 0;
376
+
377
+ .m-tabs--card &,
378
+ .m-tabs--border-card & {
379
+ padding: 16px;
380
+ border: 1px solid var(--el-border-color);
381
+ border-top: none;
382
+ }
383
+
384
+ .m-tabs--border-card & {
385
+ background: var(--el-bg-color);
386
+ }
387
+
388
+ .m-tabs--left &,
389
+ .m-tabs--right & {
390
+ flex: 1;
391
+ padding: 0 0 0 16px;
392
+ }
393
+
394
+ .m-tabs--right & {
395
+ padding: 0 16px 0 0;
396
+ }
397
+ }
398
+ }
399
+
400
+ // 响应式设计
401
+ @media (max-width: 768px) {
402
+ .m-tabs {
403
+ &__item {
404
+ padding: 6px 12px;
405
+ font-size: 13px;
406
+ }
407
+
408
+ &--left &__nav,
409
+ &--right &__nav {
410
+ width: 100px;
411
+ }
412
+ }
413
+ }
414
+ </style>