hy-app 0.4.12 → 0.4.15

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.
@@ -0,0 +1,469 @@
1
+ @use "../../libs/css/mixin.scss" as *;
2
+ @use "../../libs/css/theme" as *;
3
+
4
+ // 优惠券主题颜色变量
5
+ $coupon-primary-bg: $hy-primary !default;
6
+ $coupon-disabled-bg: $hy-info !default;
7
+ $coupon-used-bg: $hy-info !default;
8
+ $coupon-expired-bg: $hy-warning !default;
9
+ $coupon-content-bg: $hy-background--2 !default;
10
+ $coupon-light-bg: $hy-primary-light !default;
11
+
12
+ @include b(coupon) {
13
+ position: relative;
14
+ background-color: $coupon-light-bg;
15
+ border-radius: 8px;
16
+ overflow: hidden;
17
+ height: 96px;
18
+ display: flex;
19
+ align-items: stretch;
20
+ margin: 10px 0;
21
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.08);
22
+ transition: all 0.3s ease;
23
+ cursor: pointer;
24
+
25
+ // 点击交互效果
26
+ &:active {
27
+ transform: scale(0.98);
28
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
29
+ }
30
+
31
+ // 正常状态悬浮效果
32
+ &:not(.hy-coupon--disabled):not(.hy-coupon--used):not(.hy-coupon--expired) {
33
+ &:hover {
34
+ box-shadow: 0 4px 12px rgba(41, 121, 255, 0.15);
35
+ }
36
+ }
37
+
38
+ // 左侧金额区域
39
+ @include e(left) {
40
+ position: relative;
41
+ width: 96px;
42
+ background-color: $coupon-primary-bg;
43
+ color: white;
44
+ display: flex;
45
+ flex-direction: column;
46
+ align-items: center;
47
+ justify-content: center;
48
+ padding: 12px 0;
49
+ box-sizing: border-box;
50
+ overflow: hidden;
51
+
52
+ // 装饰圆点 - 右侧
53
+ &::after {
54
+ content: '';
55
+ position: absolute;
56
+ top: 50%;
57
+ right: -5px;
58
+ transform: translateY(-50%);
59
+ width: 10px;
60
+ height: 10px;
61
+ background-color: $coupon-content-bg;
62
+ border-radius: 50%;
63
+ z-index: 3;
64
+ }
65
+
66
+ // 左侧装饰圆点
67
+ &::before {
68
+ content: '';
69
+ position: absolute;
70
+ top: 50%;
71
+ left: -5px;
72
+ transform: translateY(-50%);
73
+ width: 10px;
74
+ height: 10px;
75
+ background-color: $hy-background;
76
+ border-radius: 50%;
77
+ z-index: 3;
78
+ }
79
+
80
+ // 内部容器用于背景纹理
81
+ & > .texture {
82
+ position: absolute;
83
+ top: 0;
84
+ left: 0;
85
+ right: 0;
86
+ bottom: 0;
87
+ background-image:
88
+ linear-gradient(45deg, rgba(255, 255, 255, 0.05) 25%, transparent 25%),
89
+ linear-gradient(-45deg, rgba(255, 255, 255, 0.05) 25%, transparent 25%),
90
+ linear-gradient(45deg, transparent 75%, rgba(255, 255, 255, 0.05) 75%),
91
+ linear-gradient(-45deg, transparent 75%, rgba(255, 255, 255, 0.05) 75%);
92
+ background-size: 20px 20px;
93
+ background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
94
+ z-index: 0;
95
+ }
96
+
97
+ // 金额样式
98
+ .amount {
99
+ font-size: 26px;
100
+ font-weight: bold;
101
+ line-height: 1;
102
+ z-index: 1;
103
+ position: relative;
104
+ }
105
+
106
+ .amount-symbol {
107
+ font-size: 14px;
108
+ vertical-align: top;
109
+ margin-right: 2px;
110
+ opacity: 0.9;
111
+ }
112
+
113
+ .min-spend {
114
+ font-size: 11px;
115
+ opacity: 0.85;
116
+ margin-top: 6px;
117
+ z-index: 1;
118
+ position: relative;
119
+ }
120
+ }
121
+
122
+ // 右侧内容区域
123
+ @include e(right) {
124
+ flex: 1;
125
+ padding: 14px 20px 14px 24px;
126
+ display: flex;
127
+ flex-direction: column;
128
+ justify-content: space-between;
129
+ position: relative;
130
+ background-color: $coupon-content-bg;
131
+ min-width: 0; // 防止内容溢出
132
+
133
+ .content {
134
+ flex: 1;
135
+ display: flex;
136
+ flex-direction: column;
137
+ justify-content: center;
138
+ }
139
+
140
+ .title {
141
+ font-size: 15px;
142
+ font-weight: 600;
143
+ color: $hy-text-color;
144
+ line-height: 1.3;
145
+ margin-bottom: 4px;
146
+ overflow: hidden;
147
+ text-overflow: ellipsis;
148
+ display: -webkit-box;
149
+ -webkit-line-clamp: 1;
150
+ -webkit-box-orient: vertical;
151
+ }
152
+
153
+ .subtitle {
154
+ font-size: 12px;
155
+ color: $hy-text-color--2;
156
+ line-height: 1.4;
157
+ overflow: hidden;
158
+ text-overflow: ellipsis;
159
+ display: -webkit-box;
160
+ -webkit-line-clamp: 1;
161
+ -webkit-box-orient: vertical;
162
+ margin-bottom: 6px;
163
+ }
164
+
165
+ .validity {
166
+ font-size: 12px;
167
+ color: $hy-text-color--3;
168
+ margin-top: auto;
169
+ }
170
+
171
+ // 右侧角标记
172
+ &::before {
173
+ content: '';
174
+ position: absolute;
175
+ top: 50%;
176
+ right: 0;
177
+ transform: translateY(-50%);
178
+ width: 40px;
179
+ height: 40px;
180
+ background-color: $coupon-content-bg;
181
+ border-radius: 50%;
182
+ margin-right: -20px;
183
+ }
184
+ }
185
+
186
+ // 状态样式 - 禁用、已使用、已过期
187
+ @include m(disabled) {
188
+ opacity: 0.65;
189
+ cursor: not-allowed;
190
+
191
+ @include e(left) {
192
+ background-color: $coupon-disabled-bg;
193
+ }
194
+
195
+ @include e(right) {
196
+ .title,
197
+ .subtitle {
198
+ color: $hy-text-color--3;
199
+ }
200
+
201
+ // 添加禁用标记
202
+ &::after {
203
+ content: '已禁用';
204
+ position: absolute;
205
+ top: 50%;
206
+ right: -30px;
207
+ transform: translateY(-50%) rotate(45deg);
208
+ background-color: $hy-text-color--3;
209
+ color: white;
210
+ font-size: 12px;
211
+ padding: 4px 40px;
212
+ white-space: nowrap;
213
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
214
+ }
215
+ }
216
+ }
217
+
218
+ @include m(used) {
219
+ opacity: 0.7;
220
+ cursor: not-allowed;
221
+
222
+ @include e(left) {
223
+ background-color: $hy-info;
224
+ }
225
+
226
+ @include e(right) {
227
+ .title,
228
+ .subtitle {
229
+ color: $hy-text-color--3;
230
+ }
231
+ }
232
+ }
233
+
234
+ // 已使用状态标记
235
+ @include m(used) {
236
+ @include e(right) {
237
+ &::after {
238
+ content: '已使用';
239
+ position: absolute;
240
+ top: 50%;
241
+ right: -30px;
242
+ transform: translateY(-50%) rotate(45deg);
243
+ background-color: $coupon-used-bg;
244
+ color: white;
245
+ font-size: 12px;
246
+ padding: 4px 40px;
247
+ white-space: nowrap;
248
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
249
+ }
250
+ }
251
+
252
+ // 添加已使用水印效果
253
+ &::before {
254
+ content: '已使用';
255
+ position: absolute;
256
+ top: 50%;
257
+ left: 50%;
258
+ transform: translate(-50%, -50%) rotate(-30deg);
259
+ font-size: 30px;
260
+ font-weight: bold;
261
+ color: rgba(0, 0, 0, 0.05);
262
+ pointer-events: none;
263
+ }
264
+ }
265
+
266
+ // 已过期状态标记
267
+ @include m(expired) {
268
+ @include e(left) {
269
+ background-color: $coupon-expired-bg;
270
+ }
271
+
272
+ @include e(right) {
273
+ &::after {
274
+ content: '已过期';
275
+ position: absolute;
276
+ top: 50%;
277
+ right: -30px;
278
+ transform: translateY(-50%) rotate(45deg);
279
+ background-color: $coupon-expired-bg;
280
+ color: white;
281
+ font-size: 12px;
282
+ padding: 4px 40px;
283
+ white-space: nowrap;
284
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
285
+ }
286
+ }
287
+
288
+ // 添加已过期水印效果
289
+ &::before {
290
+ content: '已过期';
291
+ position: absolute;
292
+ top: 50%;
293
+ left: 50%;
294
+ transform: translate(-50%, -50%) rotate(-30deg);
295
+ font-size: 30px;
296
+ font-weight: bold;
297
+ color: rgba(0, 0, 0, 0.05);
298
+ pointer-events: none;
299
+ }
300
+ }
301
+
302
+ // 装饰性的虚线边框效果 - 更美观的实现
303
+ .coupon-border-left {
304
+ position: absolute;
305
+ left: 96px;
306
+ top: 0;
307
+ bottom: 0;
308
+ width: 1px;
309
+ background-image: linear-gradient(transparent 50%, $hy-border-color 50%);
310
+ background-size: 1px 8px;
311
+ z-index: 1;
312
+ }
313
+
314
+ .coupon-border-right {
315
+ position: absolute;
316
+ right: 0;
317
+ top: 0;
318
+ bottom: 0;
319
+ width: 1px;
320
+ background-image: linear-gradient(transparent 50%, $hy-border-color 50%);
321
+ background-size: 1px 8px;
322
+ }
323
+
324
+ // 顶部和底部波浪形装饰
325
+ & > .top-wave,
326
+ & > .bottom-wave {
327
+ content: '';
328
+ position: absolute;
329
+ width: 100%;
330
+ height: 8px;
331
+ background-image: radial-gradient(circle at 8px 4px, transparent 4px, $coupon-content-bg 5px, transparent 6px);
332
+ background-size: 16px 8px;
333
+ left: 0;
334
+ z-index: 1;
335
+ }
336
+
337
+ & > .top-wave {
338
+ top: 0;
339
+ }
340
+
341
+ & > .bottom-wave {
342
+ bottom: 0;
343
+ transform: rotate(180deg);
344
+ }
345
+
346
+ // 修复状态标记与波浪装饰的层级关系
347
+ @include m(disabled) {
348
+ @include e(right) {
349
+ &::after {
350
+ z-index: 2;
351
+ }
352
+ }
353
+ }
354
+
355
+ @include m(used) {
356
+ @include e(right) {
357
+ &::after {
358
+ z-index: 2;
359
+ }
360
+ }
361
+ }
362
+
363
+ @include m(expired) {
364
+ @include e(right) {
365
+ &::after {
366
+ z-index: 2;
367
+ }
368
+ }
369
+ }
370
+ }
371
+
372
+ // 响应式适配
373
+ @media (max-width: 375px) {
374
+ @include b(coupon) {
375
+ height: 90px;
376
+
377
+ @include e(left) {
378
+ width: 85px;
379
+
380
+ .amount {
381
+ font-size: 22px;
382
+ }
383
+ }
384
+
385
+ @include e(right) {
386
+ padding: 12px 16px 12px 20px;
387
+
388
+ .title {
389
+ font-size: 14px;
390
+ }
391
+ }
392
+
393
+ .coupon-border-left {
394
+ left: 85px;
395
+ }
396
+ }
397
+ }
398
+
399
+ .hy-coupon {
400
+ .limit-tags {
401
+ position: absolute;
402
+ top: 8px;
403
+ right: 8px;
404
+ display: flex;
405
+ gap: 4px;
406
+ flex-wrap: wrap;
407
+ }
408
+
409
+ .limit-tag {
410
+ background-color: rgba(41, 121, 255, 0.1);
411
+ color: $hy-primary;
412
+ font-size: 10px;
413
+ padding: 2px 6px;
414
+ border-radius: 4px;
415
+ white-space: nowrap;
416
+ }
417
+
418
+ .action-button {
419
+ position: absolute;
420
+ bottom: 8px;
421
+ right: 8px;
422
+ background-color: $hy-primary;
423
+ color: white;
424
+ font-size: 12px;
425
+ padding: 4px 12px;
426
+ border-radius: 12px;
427
+ white-space: nowrap;
428
+ transition: all 0.2s ease;
429
+ }
430
+
431
+ .action-button:active {
432
+ background-color: $hy-primary;
433
+ transform: scale(0.95);
434
+ }
435
+
436
+ .coupon-tooltip {
437
+ position: absolute;
438
+ top: -30px;
439
+ left: 50%;
440
+ transform: translateX(-50%);
441
+ background-color: rgba(0, 0, 0, 0.75);
442
+ color: white;
443
+ font-size: 12px;
444
+ padding: 4px 8px;
445
+ border-radius: 4px;
446
+ white-space: nowrap;
447
+ opacity: 0;
448
+ pointer-events: none;
449
+ transition: opacity 0.3s ease;
450
+ z-index: 10;
451
+
452
+ &::after {
453
+ content: "";
454
+ position: absolute;
455
+ bottom: -4px;
456
+ left: 50%;
457
+ transform: translateX(-50%);
458
+ width: 0;
459
+ height: 0;
460
+ border-left: 4px solid transparent;
461
+ border-right: 4px solid transparent;
462
+ border-top: 4px solid rgba(0, 0, 0, 0.75);
463
+ }
464
+ }
465
+
466
+ .coupon-tooltip.show {
467
+ opacity: 1;
468
+ }
469
+ }
@@ -0,0 +1,144 @@
1
+ import type { HyCouponProps } from "./typing";
2
+ import type { CSSProperties, PropType } from "vue";
3
+ import type { CouponStatus } from "./typing";
4
+
5
+ export const defaultProps: HyCouponProps = {
6
+ amount: '',
7
+ title: '',
8
+ subTitle: '',
9
+ status: 'normal' as CouponStatus,
10
+ minSpend: 0,
11
+ validity: '',
12
+ showLeftBorder: true,
13
+ showRightBorder: true,
14
+ customStyle: {} as CSSProperties,
15
+ customClass: '',
16
+ tooltip: '',
17
+ showActionButton: false,
18
+ customButtonText: '',
19
+ isExclusive: false,
20
+ limitPerUser: 0,
21
+ usedDate: '',
22
+ expireDate: '',
23
+ disabledReason: '',
24
+ triggerReceiveOnClick: true
25
+ };
26
+
27
+ export const props = {
28
+ /** 优惠券金额 */
29
+ amount: {
30
+ type: String,
31
+ required: true
32
+ },
33
+
34
+ /** 优惠券标题 */
35
+ title: {
36
+ type: String,
37
+ required: true
38
+ },
39
+
40
+ /** 优惠券副标题 */
41
+ subTitle: {
42
+ type: String,
43
+ default: defaultProps.subTitle
44
+ },
45
+
46
+ /** 优惠券状态 */
47
+ status: {
48
+ type: String as PropType<CouponStatus>,
49
+ default: defaultProps.status,
50
+ validator: (v: string): boolean => {
51
+ return ['normal', 'disabled', 'used', 'expired'].includes(v);
52
+ }
53
+ },
54
+
55
+ /** 最小消费金额限制 */
56
+ minSpend: {
57
+ type: Number,
58
+ default: defaultProps.minSpend
59
+ },
60
+
61
+ /** 有效期 */
62
+ validity: {
63
+ type: String,
64
+ default: defaultProps.validity
65
+ },
66
+
67
+ /** 是否显示左边界装饰 */
68
+ showLeftBorder: {
69
+ type: Boolean,
70
+ default: defaultProps.showLeftBorder
71
+ },
72
+
73
+ /** 是否显示右边界装饰 */
74
+ showRightBorder: {
75
+ type: Boolean,
76
+ default: defaultProps.showRightBorder
77
+ },
78
+
79
+ /** 自定义样式 */
80
+ customStyle: {
81
+ type: Object as PropType<CSSProperties>,
82
+ default: () => ({})
83
+ },
84
+
85
+ /** 自定义类名 */
86
+ customClass: {
87
+ type: String,
88
+ default: defaultProps.customClass
89
+ },
90
+
91
+ /** 提示文本 */
92
+ tooltip: {
93
+ type: String,
94
+ default: defaultProps.tooltip
95
+ },
96
+
97
+ /** 是否显示操作按钮 */
98
+ showActionButton: {
99
+ type: Boolean,
100
+ default: defaultProps.showActionButton
101
+ },
102
+
103
+ /** 自定义按钮文本 */
104
+ customButtonText: {
105
+ type: String,
106
+ default: defaultProps.customButtonText
107
+ },
108
+
109
+ /** 是否为专属优惠券 */
110
+ isExclusive: {
111
+ type: Boolean,
112
+ default: defaultProps.isExclusive
113
+ },
114
+
115
+ /** 每用户限领数量 */
116
+ limitPerUser: {
117
+ type: Number,
118
+ default: defaultProps.limitPerUser
119
+ },
120
+
121
+ /** 使用日期(已使用状态时显示) */
122
+ usedDate: {
123
+ type: String,
124
+ default: defaultProps.usedDate
125
+ },
126
+
127
+ /** 过期日期(已过期状态时显示) */
128
+ expireDate: {
129
+ type: String,
130
+ default: defaultProps.expireDate
131
+ },
132
+
133
+ /** 禁用原因(已禁用状态时显示) */
134
+ disabledReason: {
135
+ type: String,
136
+ default: defaultProps.disabledReason
137
+ },
138
+
139
+ /** 点击时是否触发receive事件 */
140
+ triggerReceiveOnClick: {
141
+ type: Boolean,
142
+ default: defaultProps.triggerReceiveOnClick
143
+ }
144
+ };