@mc-markets/ui 1.0.90 → 1.0.92

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 (68) hide show
  1. package/README.md +243 -40
  2. package/USAGE_GUIDE.md +339 -0
  3. package/dist/404.html +22 -22
  4. package/dist/components/Tag/Tag.vue.d.ts.map +1 -1
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.mjs +10 -11
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/resolver.d.ts +26 -0
  10. package/dist/resolver.d.ts.map +1 -0
  11. package/dist/style.css +1 -1
  12. package/package.json +8 -5
  13. package/packages/components/Alert/Alert.vue +139 -139
  14. package/packages/components/Banner/Banner.vue +299 -299
  15. package/packages/components/Breadcrumb/Breadcrumb.vue +113 -113
  16. package/packages/components/Breadcrumb/BreadcrumbSeparator.vue +31 -31
  17. package/packages/components/Button/Button.vue +17 -17
  18. package/packages/components/DatePicker/DatePicker.vue +85 -85
  19. package/packages/components/Dialog/Dialog.vue +61 -61
  20. package/packages/components/Empty/Empty.vue +73 -73
  21. package/packages/components/Form/Form.vue +30 -30
  22. package/packages/components/FormItem/FormItem.vue +19 -19
  23. package/packages/components/Icon/Icon.vue +210 -210
  24. package/packages/components/Input/Input.vue +15 -15
  25. package/packages/components/Message/Message.vue +503 -503
  26. package/packages/components/NotifiMessage/NotifiMessage.vue +293 -293
  27. package/packages/components/Notification/Notification.vue +19 -19
  28. package/packages/components/Option/Option.vue +13 -13
  29. package/packages/components/OptionGroup/OptionGroup.vue +13 -13
  30. package/packages/components/Pagination/Pagination.vue +61 -61
  31. package/packages/components/Radio/Radio.vue +67 -67
  32. package/packages/components/RadioButton/RadioButton.vue +110 -110
  33. package/packages/components/RadioGroup/RadioGroup.vue +155 -155
  34. package/packages/components/Select/Select.vue +22 -22
  35. package/packages/components/Switch/Switch.vue +47 -47
  36. package/packages/components/TabCard/TabCard.vue +107 -107
  37. package/packages/components/TabCard/TabCardItem.vue +105 -105
  38. package/packages/components/Table/Table.vue +17 -17
  39. package/packages/components/Table/TableColumn.vue +20 -20
  40. package/packages/components/Tabs/TabPane.vue +79 -79
  41. package/packages/components/Tabs/Tabs.vue +267 -267
  42. package/packages/components/Tag/Tag.vue +208 -211
  43. package/packages/components/Tooltip/Tooltip.vue +58 -58
  44. package/packages/hooks/useClassName.js +23 -23
  45. package/packages/resolver.js +179 -0
  46. package/packages/styles/README.md +129 -129
  47. package/packages/styles/colorfont/iconfont.css +1 -0
  48. package/packages/styles/components/button.scss +121 -121
  49. package/packages/styles/components/checkbox.scss +18 -18
  50. package/packages/styles/components/dialog.scss +47 -47
  51. package/packages/styles/components/form.scss +18 -18
  52. package/packages/styles/components/input.scss +14 -14
  53. package/packages/styles/components/select.scss +62 -62
  54. package/packages/styles/components/table.scss +37 -37
  55. package/packages/styles/components/tabs.scss +76 -76
  56. package/packages/styles/components/tag.scss +142 -142
  57. package/packages/styles/font/iconfont.scss +363 -363
  58. package/packages/styles/index.scss +94 -94
  59. package/packages/styles/variables/border-mode.css +6 -6
  60. package/packages/styles/variables/color-modes-dark.css +143 -143
  61. package/packages/styles/variables/index.scss +5 -5
  62. package/packages/styles/variables/primitives-style.css +112 -112
  63. package/packages/styles/variables/radius-mode.css +14 -14
  64. package/packages/styles/variables/spacing-mode.css +20 -20
  65. package/packages/styles/variables/typography-desktop.css +40 -40
  66. package/packages/styles/variables/typography-mobile.css +40 -40
  67. package/packages/utils/classNames.js +23 -23
  68. package/packages/utils/styleUtils.js +105 -105
@@ -1,504 +1,504 @@
1
- <template>
2
- <teleport to="body">
3
- <transition-group name="message" tag="div" class="message-container">
4
- <div
5
- v-for="message in messages"
6
- :key="message.id"
7
- :class="[
8
- 'custom-message',
9
- `message-${message.type}`,
10
- `message-${message.placement}`,
11
- { 'message-plain': message.plain }
12
- ]"
13
- >
14
- <!-- 图标 -->
15
- <div v-if="message.showIcon" class="message-icon">
16
- <img
17
- v-if="message.customIcon"
18
- :src="message.customIcon"
19
- alt="custom icon"
20
- class="message-icon-img"
21
- />
22
- <img
23
- v-else-if="message.type === 'success'"
24
- src="https://cfdsaas-pre.oss-cn-hongkong.aliyuncs.com/mc-assets/mc-ui/alert/alert-success.png"
25
- alt="success icon"
26
- class="message-icon-img"
27
- />
28
- <img
29
- v-else-if="message.type === 'warning'"
30
- src="https://cfdsaas-pre.oss-cn-hongkong.aliyuncs.com/mc-assets/mc-ui/alert/alert-warning.png"
31
- alt="warning icon"
32
- class="message-icon-img"
33
- />
34
- <img
35
- v-else-if="message.type === 'error'"
36
- src="https://cfdsaas-pre.oss-cn-hongkong.aliyuncs.com/mc-assets/mc-ui/alert/alert-error.png"
37
- alt="error icon"
38
- class="message-icon-img"
39
- />
40
- </div>
41
-
42
- <!-- 消息内容 -->
43
- <div class="message-content">
44
- <component
45
- v-if="typeof message.message === 'function'"
46
- :is="message.message"
47
- />
48
- <div
49
- v-else-if="message.dangerouslyUseHTMLString"
50
- v-html="message.message"
51
- />
52
- <span v-else>{{ message.message }}</span>
53
-
54
- <!-- 重复数量 -->
55
- <span v-if="message.repeatNum > 1" class="message-repeat">
56
- {{ message.repeatNum }}
57
- </span>
58
- </div>
59
-
60
- <!-- 关闭按钮 -->
61
- <button
62
- v-if="message.showClose"
63
- class="message-close"
64
- @click="closeMessage(message.id)"
65
- >
66
- ×
67
- </button>
68
- </div>
69
- </transition-group>
70
- </teleport>
71
- </template>
72
-
73
- <script>
74
- import { ref } from 'vue'
75
-
76
- // 全局消息列表
77
- const messages = ref([])
78
- let messageId = 0
79
-
80
- // 创建 Message 静态方法对象
81
- const Message = {
82
- // 默认配置
83
- defaultOptions: {
84
- message: '',
85
- type: 'success',
86
- plain: false,
87
- customIcon: '',
88
- dangerouslyUseHTMLString: false,
89
- customClass: '',
90
- duration: 3000,
91
- showClose: false,
92
- showIcon: true,
93
- onClose: null,
94
- offset: 16,
95
- placement: 'top',
96
- appendTo: 'body',
97
- grouping: false,
98
- repeatNum: 1
99
- },
100
-
101
- // 显示消息
102
- show(options = {}) {
103
- // 如果是字符串,转换为配置对象
104
- if (typeof options === 'string') {
105
- options = { message: options }
106
- }
107
-
108
- const config = {
109
- ...this.defaultOptions,
110
- ...options,
111
- id: ++messageId
112
- }
113
-
114
- // 分组处理
115
- if (config.grouping) {
116
- const existingIndex = messages.value.findIndex(
117
- m => m.message === config.message && m.type === config.type && m.grouping
118
- )
119
-
120
- if (existingIndex > -1) {
121
- messages.value[existingIndex].repeatNum++
122
- return { close: () => this.close(messages.value[existingIndex].id) }
123
- }
124
- }
125
-
126
- // 添加到消息列表
127
- messages.value.push(config)
128
-
129
- // 如果设置了自动关闭时间,则自动关闭
130
- if (config.duration > 0) {
131
- setTimeout(() => {
132
- this.close(config.id)
133
- }, config.duration)
134
- }
135
-
136
- return {
137
- close: () => this.close(config.id)
138
- }
139
- },
140
-
141
- // 关闭指定消息
142
- close(id) {
143
- const index = messages.value.findIndex(m => m.id === id)
144
- if (index > -1) {
145
- const message = messages.value[index]
146
- if (message.onClose) {
147
- message.onClose(message)
148
- }
149
- messages.value.splice(index, 1)
150
- }
151
- },
152
-
153
- // 关闭所有消息
154
- closeAll() {
155
- messages.value = []
156
- },
157
-
158
- // 便捷方法
159
- success(options = {}) {
160
- if (typeof options === 'string') {
161
- options = { message: options }
162
- }
163
- return this.show({ ...options, type: 'success' })
164
- },
165
-
166
- warning(options = {}) {
167
- if (typeof options === 'string') {
168
- options = { message: options }
169
- }
170
- return this.show({ ...options, type: 'warning' })
171
- },
172
-
173
- error(options = {}) {
174
- if (typeof options === 'string') {
175
- options = { message: options }
176
- }
177
- return this.show({ ...options, type: 'error' })
178
- }
179
- }
180
-
181
- // 关闭消息的方法
182
- const closeMessage = (id) => {
183
- Message.close(id)
184
- }
185
-
186
- // Vue 组件定义
187
- export default {
188
- name: 'MMessage',
189
- setup() {
190
- return {
191
- messages,
192
- closeMessage
193
- }
194
- }
195
- }
196
-
197
- // 导出类供直接使用
198
- export { Message }
199
- </script>
200
-
201
- <style lang="scss">
202
- .message-container {
203
- position: fixed;
204
- z-index: 9999;
205
- pointer-events: none;
206
- }
207
-
208
- .custom-message {
209
- position: fixed;
210
- left: 50%;
211
- transform: translateX(-50%);
212
- min-width: 200px;
213
- max-width: 320px;
214
- padding: 12px 16px;
215
- border-radius: 8px;
216
- display: flex;
217
- align-items: center;
218
- gap: 8px;
219
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
220
- pointer-events: auto;
221
- z-index: 9999;
222
- font-size: 14px;
223
-
224
- // 位置控制
225
- &.message-top {
226
- top: 20px;
227
-
228
- &:nth-child(2) { top: 70px; }
229
- &:nth-child(3) { top: 120px; }
230
- &:nth-child(4) { top: 170px; }
231
- &:nth-child(5) { top: 220px; }
232
- }
233
-
234
- &.message-top-left {
235
- top: 20px;
236
- left: 20px;
237
- transform: none;
238
-
239
- &:nth-child(2) { top: 70px; }
240
- &:nth-child(3) { top: 120px; }
241
- &:nth-child(4) { top: 170px; }
242
- &:nth-child(5) { top: 220px; }
243
- }
244
-
245
- &.message-top-right {
246
- top: 20px;
247
- right: 20px;
248
- left: auto;
249
- transform: none;
250
-
251
- &:nth-child(2) { top: 70px; }
252
- &:nth-child(3) { top: 120px; }
253
- &:nth-child(4) { top: 170px; }
254
- &:nth-child(5) { top: 220px; }
255
- }
256
-
257
- &.message-bottom {
258
- bottom: 20px;
259
- top: auto;
260
-
261
- &:nth-child(2) { bottom: 70px; }
262
- &:nth-child(3) { bottom: 120px; }
263
- &:nth-child(4) { bottom: 170px; }
264
- &:nth-child(5) { bottom: 220px; }
265
- }
266
-
267
- &.message-bottom-left {
268
- bottom: 20px;
269
- left: 20px;
270
- top: auto;
271
- transform: none;
272
-
273
- &:nth-child(2) { bottom: 70px; }
274
- &:nth-child(3) { bottom: 120px; }
275
- &:nth-child(4) { bottom: 170px; }
276
- &:nth-child(5) { bottom: 220px; }
277
- }
278
-
279
- &.message-bottom-right {
280
- bottom: 20px;
281
- right: 20px;
282
- left: auto;
283
- top: auto;
284
- transform: none;
285
-
286
- &:nth-child(2) { bottom: 70px; }
287
- &:nth-child(3) { bottom: 120px; }
288
- &:nth-child(4) { bottom: 170px; }
289
- &:nth-child(5) { bottom: 220px; }
290
- }
291
-
292
- .message-icon {
293
- flex-shrink: 0;
294
- display: flex;
295
- align-items: center;
296
-
297
- .message-icon-img {
298
- width: 16px;
299
- height: 16px;
300
- object-fit: contain;
301
- }
302
- }
303
-
304
- .message-content {
305
- flex: 1;
306
- line-height: 1.4;
307
- position: relative;
308
-
309
- .message-repeat {
310
- position: absolute;
311
- top: -8px;
312
- right: -8px;
313
- display: flex;
314
- align-items: center;
315
- justify-content: center;
316
- background: #666;
317
- color: white;
318
- font-size: 10px;
319
- font-weight: bold;
320
- min-width: 16px;
321
- height: 16px;
322
- padding: 0 4px;
323
- border-radius: 8px;
324
- border: 2px solid white;
325
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
326
- }
327
- }
328
-
329
- .message-close {
330
- flex-shrink: 0;
331
- border: none;
332
- background: transparent;
333
- cursor: pointer;
334
- display: flex;
335
- align-items: center;
336
- justify-content: center;
337
- padding: 4px;
338
- margin-left: 8px;
339
- opacity: 0.6;
340
- transition: opacity 0.2s ease;
341
- font-size: 24px;
342
- width: 20px;
343
- height: 20px;
344
- border-radius: 50%;
345
- color: var(--icon-tertiary, #999);
346
-
347
- &:hover {
348
- opacity: 1;
349
- background: rgba(0, 0, 0, 0.1);
350
- }
351
- }
352
-
353
- // 不同类型的样式 - 统一使用 bg-tertiary-hover 背景
354
- &.message-success {
355
- background-color: var(--bg-tertiary-hover, #f5f5f5);
356
- color: var(--all-green-4, #67c23a);
357
- border: 1px solid var(--bg-tertiary-hover, #f5f5f5);
358
-
359
- .message-icon {
360
- color: var(--all-green-4, #67c23a);
361
- }
362
-
363
- .message-repeat {
364
- background: var(--all-green-4, #67c23a);
365
- border-color: var(--all-green-4, #67c23a);
366
- }
367
-
368
- &.message-plain {
369
- background: var(--all-green-4, #67c23a);
370
- border: 1px solid var(--all-green-4, #67c23a);
371
- color: #fff;
372
-
373
- .message-icon {
374
- color: #fff;
375
- }
376
- }
377
- }
378
-
379
- &.message-warning {
380
- background-color: var(--bg-tertiary-hover, #f5f5f5);
381
- color: var(--text-warning-primary, #e6a23c);
382
- border: 1px solid var(--bg-tertiary-hover, #f5f5f5);
383
-
384
- .message-icon {
385
- color: var(--text-warning-primary, #e6a23c);
386
- }
387
-
388
- .message-repeat {
389
- background: var(--text-warning-primary, #e6a23c);
390
- border-color: var(--text-warning-primary, #e6a23c);
391
- }
392
-
393
- &.message-plain {
394
- background: var(--text-warning-primary, #e6a23c);
395
- border: 1px solid var(--text-warning-primary, #e6a23c);
396
- color: #fff;
397
-
398
- .message-icon {
399
- color: #fff;
400
- }
401
- }
402
- }
403
-
404
- &.message-error {
405
- background-color: var(--bg-tertiary-hover, #f5f5f5);
406
- color: var(--text-error-primary, #f56c6c);
407
- border: 1px solid var(--bg-tertiary-hover, #f5f5f5);
408
-
409
- .message-icon {
410
- color: var(--text-error-primary, #f56c6c);
411
- }
412
-
413
- .message-repeat {
414
- background: var(--text-error-primary, #f56c6c);
415
- border-color: var(--text-error-primary, #f56c6c);
416
- }
417
-
418
- &.message-plain {
419
- background: var(--text-error-primary, #f56c6c);
420
- border: 1px solid var(--text-error-primary, #f56c6c);
421
- color: #fff;
422
-
423
- .message-icon {
424
- color: #fff;
425
- }
426
- }
427
- }
428
- }
429
-
430
- // 动画效果
431
- .message-enter-active {
432
- transition: all 0.3s ease;
433
- }
434
-
435
- .message-leave-active {
436
- transition: all 0.3s ease;
437
- }
438
-
439
- .message-enter-from {
440
- opacity: 0;
441
- transform: translateX(-50%) translateY(-20px);
442
- }
443
-
444
- .message-leave-to {
445
- opacity: 0;
446
- transform: translateX(-50%) translateY(-20px);
447
- }
448
-
449
- .message-move {
450
- transition: transform 0.3s ease;
451
- }
452
-
453
- // 不同位置的动画
454
- .message-top-left {
455
- &.message-enter-from,
456
- &.message-leave-to {
457
- transform: translateX(-20px);
458
- }
459
- }
460
-
461
- .message-top-right {
462
- &.message-enter-from,
463
- &.message-leave-to {
464
- transform: translateX(20px);
465
- }
466
- }
467
-
468
- .message-bottom {
469
- &.message-enter-from,
470
- &.message-leave-to {
471
- transform: translateX(-50%) translateY(20px);
472
- }
473
- }
474
-
475
- .message-bottom-left {
476
- &.message-enter-from,
477
- &.message-leave-to {
478
- transform: translateX(-20px);
479
- }
480
- }
481
-
482
- .message-bottom-right {
483
- &.message-enter-from,
484
- &.message-leave-to {
485
- transform: translateX(20px);
486
- }
487
- }
488
-
489
- // 响应式设计
490
- @media (max-width: 480px) {
491
- .custom-message {
492
- min-width: calc(100vw - 40px);
493
- max-width: calc(100vw - 40px);
494
- left: 20px !important;
495
- right: 20px !important;
496
- transform: none !important;
497
-
498
- &.message-enter-from,
499
- &.message-leave-to {
500
- transform: translateY(-20px) !important;
501
- }
502
- }
503
- }
1
+ <template>
2
+ <teleport to="body">
3
+ <transition-group name="message" tag="div" class="message-container">
4
+ <div
5
+ v-for="message in messages"
6
+ :key="message.id"
7
+ :class="[
8
+ 'custom-message',
9
+ `message-${message.type}`,
10
+ `message-${message.placement}`,
11
+ { 'message-plain': message.plain }
12
+ ]"
13
+ >
14
+ <!-- 图标 -->
15
+ <div v-if="message.showIcon" class="message-icon">
16
+ <img
17
+ v-if="message.customIcon"
18
+ :src="message.customIcon"
19
+ alt="custom icon"
20
+ class="message-icon-img"
21
+ />
22
+ <img
23
+ v-else-if="message.type === 'success'"
24
+ src="https://cfdsaas-pre.oss-cn-hongkong.aliyuncs.com/mc-assets/mc-ui/alert/alert-success.png"
25
+ alt="success icon"
26
+ class="message-icon-img"
27
+ />
28
+ <img
29
+ v-else-if="message.type === 'warning'"
30
+ src="https://cfdsaas-pre.oss-cn-hongkong.aliyuncs.com/mc-assets/mc-ui/alert/alert-warning.png"
31
+ alt="warning icon"
32
+ class="message-icon-img"
33
+ />
34
+ <img
35
+ v-else-if="message.type === 'error'"
36
+ src="https://cfdsaas-pre.oss-cn-hongkong.aliyuncs.com/mc-assets/mc-ui/alert/alert-error.png"
37
+ alt="error icon"
38
+ class="message-icon-img"
39
+ />
40
+ </div>
41
+
42
+ <!-- 消息内容 -->
43
+ <div class="message-content">
44
+ <component
45
+ v-if="typeof message.message === 'function'"
46
+ :is="message.message"
47
+ />
48
+ <div
49
+ v-else-if="message.dangerouslyUseHTMLString"
50
+ v-html="message.message"
51
+ />
52
+ <span v-else>{{ message.message }}</span>
53
+
54
+ <!-- 重复数量 -->
55
+ <span v-if="message.repeatNum > 1" class="message-repeat">
56
+ {{ message.repeatNum }}
57
+ </span>
58
+ </div>
59
+
60
+ <!-- 关闭按钮 -->
61
+ <button
62
+ v-if="message.showClose"
63
+ class="message-close"
64
+ @click="closeMessage(message.id)"
65
+ >
66
+ ×
67
+ </button>
68
+ </div>
69
+ </transition-group>
70
+ </teleport>
71
+ </template>
72
+
73
+ <script>
74
+ import { ref } from 'vue'
75
+
76
+ // 全局消息列表
77
+ const messages = ref([])
78
+ let messageId = 0
79
+
80
+ // 创建 Message 静态方法对象
81
+ const Message = {
82
+ // 默认配置
83
+ defaultOptions: {
84
+ message: '',
85
+ type: 'success',
86
+ plain: false,
87
+ customIcon: '',
88
+ dangerouslyUseHTMLString: false,
89
+ customClass: '',
90
+ duration: 3000,
91
+ showClose: false,
92
+ showIcon: true,
93
+ onClose: null,
94
+ offset: 16,
95
+ placement: 'top',
96
+ appendTo: 'body',
97
+ grouping: false,
98
+ repeatNum: 1
99
+ },
100
+
101
+ // 显示消息
102
+ show(options = {}) {
103
+ // 如果是字符串,转换为配置对象
104
+ if (typeof options === 'string') {
105
+ options = { message: options }
106
+ }
107
+
108
+ const config = {
109
+ ...this.defaultOptions,
110
+ ...options,
111
+ id: ++messageId
112
+ }
113
+
114
+ // 分组处理
115
+ if (config.grouping) {
116
+ const existingIndex = messages.value.findIndex(
117
+ m => m.message === config.message && m.type === config.type && m.grouping
118
+ )
119
+
120
+ if (existingIndex > -1) {
121
+ messages.value[existingIndex].repeatNum++
122
+ return { close: () => this.close(messages.value[existingIndex].id) }
123
+ }
124
+ }
125
+
126
+ // 添加到消息列表
127
+ messages.value.push(config)
128
+
129
+ // 如果设置了自动关闭时间,则自动关闭
130
+ if (config.duration > 0) {
131
+ setTimeout(() => {
132
+ this.close(config.id)
133
+ }, config.duration)
134
+ }
135
+
136
+ return {
137
+ close: () => this.close(config.id)
138
+ }
139
+ },
140
+
141
+ // 关闭指定消息
142
+ close(id) {
143
+ const index = messages.value.findIndex(m => m.id === id)
144
+ if (index > -1) {
145
+ const message = messages.value[index]
146
+ if (message.onClose) {
147
+ message.onClose(message)
148
+ }
149
+ messages.value.splice(index, 1)
150
+ }
151
+ },
152
+
153
+ // 关闭所有消息
154
+ closeAll() {
155
+ messages.value = []
156
+ },
157
+
158
+ // 便捷方法
159
+ success(options = {}) {
160
+ if (typeof options === 'string') {
161
+ options = { message: options }
162
+ }
163
+ return this.show({ ...options, type: 'success' })
164
+ },
165
+
166
+ warning(options = {}) {
167
+ if (typeof options === 'string') {
168
+ options = { message: options }
169
+ }
170
+ return this.show({ ...options, type: 'warning' })
171
+ },
172
+
173
+ error(options = {}) {
174
+ if (typeof options === 'string') {
175
+ options = { message: options }
176
+ }
177
+ return this.show({ ...options, type: 'error' })
178
+ }
179
+ }
180
+
181
+ // 关闭消息的方法
182
+ const closeMessage = (id) => {
183
+ Message.close(id)
184
+ }
185
+
186
+ // Vue 组件定义
187
+ export default {
188
+ name: 'MMessage',
189
+ setup() {
190
+ return {
191
+ messages,
192
+ closeMessage
193
+ }
194
+ }
195
+ }
196
+
197
+ // 导出类供直接使用
198
+ export { Message }
199
+ </script>
200
+
201
+ <style lang="scss">
202
+ .message-container {
203
+ position: fixed;
204
+ z-index: 9999;
205
+ pointer-events: none;
206
+ }
207
+
208
+ .custom-message {
209
+ position: fixed;
210
+ left: 50%;
211
+ transform: translateX(-50%);
212
+ min-width: 200px;
213
+ max-width: 320px;
214
+ padding: 12px 16px;
215
+ border-radius: 8px;
216
+ display: flex;
217
+ align-items: center;
218
+ gap: 8px;
219
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
220
+ pointer-events: auto;
221
+ z-index: 9999;
222
+ font-size: 14px;
223
+
224
+ // 位置控制
225
+ &.message-top {
226
+ top: 20px;
227
+
228
+ &:nth-child(2) { top: 70px; }
229
+ &:nth-child(3) { top: 120px; }
230
+ &:nth-child(4) { top: 170px; }
231
+ &:nth-child(5) { top: 220px; }
232
+ }
233
+
234
+ &.message-top-left {
235
+ top: 20px;
236
+ left: 20px;
237
+ transform: none;
238
+
239
+ &:nth-child(2) { top: 70px; }
240
+ &:nth-child(3) { top: 120px; }
241
+ &:nth-child(4) { top: 170px; }
242
+ &:nth-child(5) { top: 220px; }
243
+ }
244
+
245
+ &.message-top-right {
246
+ top: 20px;
247
+ right: 20px;
248
+ left: auto;
249
+ transform: none;
250
+
251
+ &:nth-child(2) { top: 70px; }
252
+ &:nth-child(3) { top: 120px; }
253
+ &:nth-child(4) { top: 170px; }
254
+ &:nth-child(5) { top: 220px; }
255
+ }
256
+
257
+ &.message-bottom {
258
+ bottom: 20px;
259
+ top: auto;
260
+
261
+ &:nth-child(2) { bottom: 70px; }
262
+ &:nth-child(3) { bottom: 120px; }
263
+ &:nth-child(4) { bottom: 170px; }
264
+ &:nth-child(5) { bottom: 220px; }
265
+ }
266
+
267
+ &.message-bottom-left {
268
+ bottom: 20px;
269
+ left: 20px;
270
+ top: auto;
271
+ transform: none;
272
+
273
+ &:nth-child(2) { bottom: 70px; }
274
+ &:nth-child(3) { bottom: 120px; }
275
+ &:nth-child(4) { bottom: 170px; }
276
+ &:nth-child(5) { bottom: 220px; }
277
+ }
278
+
279
+ &.message-bottom-right {
280
+ bottom: 20px;
281
+ right: 20px;
282
+ left: auto;
283
+ top: auto;
284
+ transform: none;
285
+
286
+ &:nth-child(2) { bottom: 70px; }
287
+ &:nth-child(3) { bottom: 120px; }
288
+ &:nth-child(4) { bottom: 170px; }
289
+ &:nth-child(5) { bottom: 220px; }
290
+ }
291
+
292
+ .message-icon {
293
+ flex-shrink: 0;
294
+ display: flex;
295
+ align-items: center;
296
+
297
+ .message-icon-img {
298
+ width: 16px;
299
+ height: 16px;
300
+ object-fit: contain;
301
+ }
302
+ }
303
+
304
+ .message-content {
305
+ flex: 1;
306
+ line-height: 1.4;
307
+ position: relative;
308
+
309
+ .message-repeat {
310
+ position: absolute;
311
+ top: -8px;
312
+ right: -8px;
313
+ display: flex;
314
+ align-items: center;
315
+ justify-content: center;
316
+ background: #666;
317
+ color: white;
318
+ font-size: 10px;
319
+ font-weight: bold;
320
+ min-width: 16px;
321
+ height: 16px;
322
+ padding: 0 4px;
323
+ border-radius: 8px;
324
+ border: 2px solid white;
325
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
326
+ }
327
+ }
328
+
329
+ .message-close {
330
+ flex-shrink: 0;
331
+ border: none;
332
+ background: transparent;
333
+ cursor: pointer;
334
+ display: flex;
335
+ align-items: center;
336
+ justify-content: center;
337
+ padding: 4px;
338
+ margin-left: 8px;
339
+ opacity: 0.6;
340
+ transition: opacity 0.2s ease;
341
+ font-size: 24px;
342
+ width: 20px;
343
+ height: 20px;
344
+ border-radius: 50%;
345
+ color: var(--icon-tertiary, #999);
346
+
347
+ &:hover {
348
+ opacity: 1;
349
+ background: rgba(0, 0, 0, 0.1);
350
+ }
351
+ }
352
+
353
+ // 不同类型的样式 - 统一使用 bg-tertiary-hover 背景
354
+ &.message-success {
355
+ background-color: var(--bg-tertiary-hover, #f5f5f5);
356
+ color: var(--all-green-4, #67c23a);
357
+ border: 1px solid var(--bg-tertiary-hover, #f5f5f5);
358
+
359
+ .message-icon {
360
+ color: var(--all-green-4, #67c23a);
361
+ }
362
+
363
+ .message-repeat {
364
+ background: var(--all-green-4, #67c23a);
365
+ border-color: var(--all-green-4, #67c23a);
366
+ }
367
+
368
+ &.message-plain {
369
+ background: var(--all-green-4, #67c23a);
370
+ border: 1px solid var(--all-green-4, #67c23a);
371
+ color: #fff;
372
+
373
+ .message-icon {
374
+ color: #fff;
375
+ }
376
+ }
377
+ }
378
+
379
+ &.message-warning {
380
+ background-color: var(--bg-tertiary-hover, #f5f5f5);
381
+ color: var(--text-warning-primary, #e6a23c);
382
+ border: 1px solid var(--bg-tertiary-hover, #f5f5f5);
383
+
384
+ .message-icon {
385
+ color: var(--text-warning-primary, #e6a23c);
386
+ }
387
+
388
+ .message-repeat {
389
+ background: var(--text-warning-primary, #e6a23c);
390
+ border-color: var(--text-warning-primary, #e6a23c);
391
+ }
392
+
393
+ &.message-plain {
394
+ background: var(--text-warning-primary, #e6a23c);
395
+ border: 1px solid var(--text-warning-primary, #e6a23c);
396
+ color: #fff;
397
+
398
+ .message-icon {
399
+ color: #fff;
400
+ }
401
+ }
402
+ }
403
+
404
+ &.message-error {
405
+ background-color: var(--bg-tertiary-hover, #f5f5f5);
406
+ color: var(--text-error-primary, #f56c6c);
407
+ border: 1px solid var(--bg-tertiary-hover, #f5f5f5);
408
+
409
+ .message-icon {
410
+ color: var(--text-error-primary, #f56c6c);
411
+ }
412
+
413
+ .message-repeat {
414
+ background: var(--text-error-primary, #f56c6c);
415
+ border-color: var(--text-error-primary, #f56c6c);
416
+ }
417
+
418
+ &.message-plain {
419
+ background: var(--text-error-primary, #f56c6c);
420
+ border: 1px solid var(--text-error-primary, #f56c6c);
421
+ color: #fff;
422
+
423
+ .message-icon {
424
+ color: #fff;
425
+ }
426
+ }
427
+ }
428
+ }
429
+
430
+ // 动画效果
431
+ .message-enter-active {
432
+ transition: all 0.3s ease;
433
+ }
434
+
435
+ .message-leave-active {
436
+ transition: all 0.3s ease;
437
+ }
438
+
439
+ .message-enter-from {
440
+ opacity: 0;
441
+ transform: translateX(-50%) translateY(-20px);
442
+ }
443
+
444
+ .message-leave-to {
445
+ opacity: 0;
446
+ transform: translateX(-50%) translateY(-20px);
447
+ }
448
+
449
+ .message-move {
450
+ transition: transform 0.3s ease;
451
+ }
452
+
453
+ // 不同位置的动画
454
+ .message-top-left {
455
+ &.message-enter-from,
456
+ &.message-leave-to {
457
+ transform: translateX(-20px);
458
+ }
459
+ }
460
+
461
+ .message-top-right {
462
+ &.message-enter-from,
463
+ &.message-leave-to {
464
+ transform: translateX(20px);
465
+ }
466
+ }
467
+
468
+ .message-bottom {
469
+ &.message-enter-from,
470
+ &.message-leave-to {
471
+ transform: translateX(-50%) translateY(20px);
472
+ }
473
+ }
474
+
475
+ .message-bottom-left {
476
+ &.message-enter-from,
477
+ &.message-leave-to {
478
+ transform: translateX(-20px);
479
+ }
480
+ }
481
+
482
+ .message-bottom-right {
483
+ &.message-enter-from,
484
+ &.message-leave-to {
485
+ transform: translateX(20px);
486
+ }
487
+ }
488
+
489
+ // 响应式设计
490
+ @media (max-width: 480px) {
491
+ .custom-message {
492
+ min-width: calc(100vw - 40px);
493
+ max-width: calc(100vw - 40px);
494
+ left: 20px !important;
495
+ right: 20px !important;
496
+ transform: none !important;
497
+
498
+ &.message-enter-from,
499
+ &.message-leave-to {
500
+ transform: translateY(-20px) !important;
501
+ }
502
+ }
503
+ }
504
504
  </style>