@taskon/widget-react 0.0.1

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 (37) hide show
  1. package/README.md +1064 -0
  2. package/dist/CommunityTaskList.css +5010 -0
  3. package/dist/EligibilityInfo.css +1966 -0
  4. package/dist/LeaderboardWidget.css +815 -0
  5. package/dist/Quest.css +4584 -0
  6. package/dist/Table.css +389 -0
  7. package/dist/TaskOnProvider.css +163 -0
  8. package/dist/WidgetShell.css +182 -0
  9. package/dist/chunks/CommunityTaskList-CrH6r4Av.js +6886 -0
  10. package/dist/chunks/EligibilityInfo-DesW9-k9.js +24900 -0
  11. package/dist/chunks/LeaderboardWidget-BSGpHKTk.js +1156 -0
  12. package/dist/chunks/Quest-uSIVq78I.js +8581 -0
  13. package/dist/chunks/Table-CWGf2FKV.js +449 -0
  14. package/dist/chunks/TaskOnProvider-QMwxGL44.js +1435 -0
  15. package/dist/chunks/ThemeProvider-Cs8IUVQj.js +1118 -0
  16. package/dist/chunks/WidgetShell-NlOgn1x5.js +1517 -0
  17. package/dist/chunks/common-ja-DWhTaFHb.js +23 -0
  18. package/dist/chunks/common-ko-80ezXsMG.js +23 -0
  19. package/dist/chunks/index-CwMvO_wZ.js +777 -0
  20. package/dist/chunks/leaderboardwidget-ja-Bj6gz6y1.js +119 -0
  21. package/dist/chunks/leaderboardwidget-ko-f1cLO9ic.js +119 -0
  22. package/dist/chunks/useToast-BGJhd3BX.js +93 -0
  23. package/dist/chunks/useWidgetLocale-BVcopbZS.js +74 -0
  24. package/dist/chunks/usercenter-ja-DBj_dtuz.js +329 -0
  25. package/dist/chunks/usercenter-ko-DYTkHAld.js +329 -0
  26. package/dist/community-task.d.ts +451 -0
  27. package/dist/community-task.js +9 -0
  28. package/dist/core.d.ts +803 -0
  29. package/dist/core.js +22 -0
  30. package/dist/index.css +3662 -0
  31. package/dist/index.d.ts +1627 -0
  32. package/dist/index.js +7372 -0
  33. package/dist/leaderboard.d.ts +547 -0
  34. package/dist/leaderboard.js +17 -0
  35. package/dist/quest.d.ts +389 -0
  36. package/dist/quest.js +8 -0
  37. package/package.json +97 -0
@@ -0,0 +1,1966 @@
1
+ /**
2
+ * Textarea 通用组件样式
3
+ * @description 复刻 Vue 版本 BaseTextareaPro.vue 样式
4
+ * 使用 taskon-textarea 命名空间
5
+ */
6
+
7
+ /* ==================== 容器 ==================== */
8
+ .taskon-textarea-wrap {
9
+ position: relative;
10
+ font-size: 0;
11
+ }
12
+
13
+ /* ==================== 文本域 ==================== */
14
+ .taskon-textarea {
15
+ width: 100%;
16
+ min-height: 100px;
17
+ padding: 12px;
18
+ padding-bottom: 36px; /* 给计数器留空间 */
19
+ border-radius: 6px;
20
+ border: 1px solid rgba(255, 255, 255, 0.1);
21
+ background: rgba(255, 255, 255, 0.04);
22
+ color: var(--taskon-color-text, #fff);
23
+ font-size: 14px;
24
+ line-height: 1.5;
25
+ resize: none;
26
+ outline: none;
27
+ transition: border-color 0.2s;
28
+ }
29
+
30
+ .taskon-textarea:focus {
31
+ border-color: var(--taskon-color-primary, #cbff01);
32
+ }
33
+
34
+ .taskon-textarea:disabled {
35
+ opacity: 0.6;
36
+ cursor: not-allowed;
37
+ }
38
+
39
+ .taskon-textarea--error {
40
+ border-color: #eb5757;
41
+ }
42
+
43
+ .taskon-textarea::placeholder {
44
+ color: var(--taskon-color-text-tertiary, #666);
45
+ }
46
+
47
+ /* ==================== 字数统计 ==================== */
48
+ .taskon-textarea-count {
49
+ position: absolute;
50
+ right: 20px;
51
+ bottom: 12px;
52
+ font-weight: 400;
53
+ font-size: 14px;
54
+ line-height: 20px;
55
+ color: rgba(255, 255, 255, 0.6);
56
+ }
57
+
58
+ .taskon-textarea-count-current {
59
+ color: #fff;
60
+ }
61
+
62
+ /* ==================== 响应式 ==================== */
63
+ @media (max-width: 750px) {
64
+ .taskon-textarea {
65
+ min-height: 26.667vw;
66
+ padding: 3.2vw;
67
+ padding-bottom: 8vw; /* 给计数器留空间 */
68
+ font-size: 3.733vw;
69
+ }
70
+
71
+ .taskon-textarea-count {
72
+ right: 2.933vw;
73
+ bottom: 2.667vw;
74
+ font-size: 2.933vw;
75
+ line-height: 2.667vw;
76
+ }
77
+ }
78
+ /**
79
+ * TitleExpress 组件样式
80
+ * @module components/TitleExpress
81
+ */
82
+
83
+ /* 可点击链接 - 统一蓝色加下划线样式 */
84
+ .taskon-title-express-link {
85
+ display: inline;
86
+ color: #54aeff;
87
+ cursor: pointer;
88
+ text-decoration: underline;
89
+ transition: opacity 0.2s ease;
90
+ }
91
+
92
+ .taskon-title-express-link:hover {
93
+ opacity: 0.8;
94
+ }
95
+
96
+ /* 可复制文本 */
97
+ .taskon-title-express-copy {
98
+ display: inline;
99
+ color: var(--taskon-color-secondary, #cbff01);
100
+ cursor: pointer;
101
+ }
102
+
103
+ /* Radix Popover 内容 */
104
+ .taskon-title-express-popover-content {
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ gap: 6px;
109
+ padding: 8px 12px;
110
+ background: var(--taskon-color-bg-popover, #2a2a2a);
111
+ border-radius: 8px;
112
+ border: none;
113
+ outline: none;
114
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
115
+ cursor: pointer;
116
+ font-size: 14px;
117
+ font-weight: 500;
118
+ line-height: 18px;
119
+ color: var(--taskon-color-text, #fff);
120
+ z-index: 9999;
121
+ animation: taskon-popover-fade-in 0.15s ease;
122
+ }
123
+
124
+ .taskon-title-express-popover-content:focus {
125
+ outline: none;
126
+ }
127
+
128
+ .taskon-title-express-popover-content:hover {
129
+ background: var(--taskon-color-bg-popover-hover, #3a3a3a);
130
+ }
131
+
132
+ /* 复制图标 */
133
+ .taskon-title-express-copy-icon {
134
+ width: 14px;
135
+ height: 14px;
136
+ flex-shrink: 0;
137
+ }
138
+
139
+ /* Radix Popover 箭头 */
140
+ .taskon-title-express-popover-arrow {
141
+ fill: var(--taskon-color-bg-popover, #2a2a2a);
142
+ }
143
+
144
+ /* 动画 */
145
+ @keyframes taskon-popover-fade-in {
146
+ from {
147
+ opacity: 0;
148
+ transform: translateY(2px);
149
+ }
150
+ to {
151
+ opacity: 1;
152
+ transform: translateY(0);
153
+ }
154
+ }
155
+
156
+ /* 响应式样式(移动端) */
157
+ @media (max-width: 750px) {
158
+ .taskon-title-express-popover-content {
159
+ padding: 2.13vw 3.2vw;
160
+ font-size: 3.73vw;
161
+ line-height: 4.8vw;
162
+ border-radius: 2.13vw;
163
+ gap: 1.6vw;
164
+ }
165
+
166
+ .taskon-title-express-copy-icon {
167
+ width: 3.73vw;
168
+ height: 3.73vw;
169
+ }
170
+ }
171
+ /**
172
+ * TipPopover 组件样式
173
+ * 设计原则:组件内部不包含 margin,需要间距由外部控制
174
+ */
175
+
176
+ .taskon-tip-popover-trigger {
177
+ display: inline-flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ padding: 0;
181
+ border: none;
182
+ background: transparent;
183
+ cursor: pointer;
184
+ color: var(--taskon-text-tertiary, rgba(255, 255, 255, 0.4));
185
+ outline: none;
186
+ }
187
+
188
+ .taskon-tip-popover-trigger:hover,
189
+ .taskon-tip-popover-trigger:focus {
190
+ color: var(--taskon-text-tertiary, rgba(255, 255, 255, 0.4));
191
+ background: transparent;
192
+ outline: none;
193
+ }
194
+
195
+ /* Custom children trigger - reset button styles */
196
+ .taskon-tip-popover-trigger--custom {
197
+ cursor: pointer;
198
+ }
199
+
200
+ .taskon-tip-popover-content {
201
+ max-width: 266px;
202
+ padding: 12px 16px;
203
+ border-radius: 8px;
204
+ border: none;
205
+ outline: none;
206
+ background: var(--taskon-bg-elevated, #2a2a2a);
207
+ color: var(--taskon-text-primary, #fff);
208
+ font-size: 13px;
209
+ line-height: 1.5;
210
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
211
+ /* z-index 需要大于 Dialog (9999) 才能在弹窗中正常显示 */
212
+ z-index: 10000;
213
+ animation: taskon-tip-popover-fade-in 0.15s ease;
214
+ }
215
+
216
+ .taskon-tip-popover-content:focus {
217
+ outline: none;
218
+ }
219
+
220
+ .taskon-tip-popover-arrow {
221
+ fill: var(--taskon-bg-elevated, #2a2a2a);
222
+ }
223
+
224
+ @keyframes taskon-tip-popover-fade-in {
225
+ from {
226
+ opacity: 0;
227
+ transform: scale(0.96);
228
+ }
229
+ to {
230
+ opacity: 1;
231
+ transform: scale(1);
232
+ }
233
+ }
234
+
235
+ /* Mobile styles */
236
+ @media (max-width: 750px) {
237
+ .taskon-tip-popover-content {
238
+ max-width: 60vw;
239
+ padding: 2.5vw 3.5vw;
240
+ font-size: 3vw;
241
+ }
242
+ }
243
+ /**
244
+ * PowTask Styles
245
+ * @description POW 任务样式
246
+ * 遵循 Widget 命名规范:.taskon-{widget-name}-{element}
247
+ */
248
+
249
+ /* ============================================
250
+ * POW Task Container
251
+ * ============================================ */
252
+ .taskon-pow-task {
253
+ /* 继承 TaskCardBase 的样式 */
254
+ }
255
+
256
+ /* ============================================
257
+ * POW Description
258
+ * ============================================ */
259
+ .taskon-pow-desc {
260
+ font-size: 14px;
261
+ line-height: 21px;
262
+ color: rgba(255, 255, 255, 0.8);
263
+ word-break: break-word;
264
+ }
265
+
266
+ .taskon-pow-desc a {
267
+ color: var(--taskon-primary-color, #3b82f6);
268
+ text-decoration: none;
269
+ }
270
+
271
+ .taskon-pow-desc a:hover {
272
+ text-decoration: underline;
273
+ }
274
+
275
+ /* ============================================
276
+ * POW Input Area
277
+ * ============================================ */
278
+ .taskon-pow-input-area {
279
+ margin-top: 15px;
280
+ }
281
+
282
+ /* ============================================
283
+ * URL Input Row
284
+ * ============================================ */
285
+ .taskon-pow-url-row {
286
+ display: flex;
287
+ align-items: center;
288
+ gap: 15px;
289
+ }
290
+
291
+ .taskon-pow-input {
292
+ flex: 1;
293
+ padding: 10px 12px;
294
+ border: 1px solid rgba(255, 255, 255, 0.2);
295
+ border-radius: 6px;
296
+ background: rgba(255, 255, 255, 0.05);
297
+ color: #fff;
298
+ font-size: 14px;
299
+ outline: none;
300
+ transition: border-color 0.2s ease;
301
+ }
302
+
303
+ .taskon-pow-input:focus {
304
+ border-color: var(--taskon-primary-color, #3b82f6);
305
+ }
306
+
307
+ .taskon-pow-input:disabled {
308
+ opacity: 0.5;
309
+ cursor: not-allowed;
310
+ }
311
+
312
+ .taskon-pow-input::placeholder {
313
+ color: rgba(255, 255, 255, 0.4);
314
+ }
315
+
316
+ /* ============================================
317
+ * Text Input Row
318
+ * ============================================ */
319
+ .taskon-pow-text-row {
320
+ display: flex;
321
+ align-items: flex-end;
322
+ gap: 15px;
323
+ }
324
+
325
+ .taskon-pow-text-row .taskon-textarea-wrap {
326
+ flex: 1;
327
+ }
328
+
329
+ /* ============================================
330
+ * Image Upload Area - 与 Vue 版本 PowImageUploader 一致
331
+ * ============================================ */
332
+ .taskon-pow-image-uploader {
333
+ margin-top: 20px;
334
+ display: flex;
335
+ align-items: center;
336
+ }
337
+
338
+ .taskon-pow-image-upload-area {
339
+ flex: 1;
340
+ position: relative;
341
+ display: flex;
342
+ flex-direction: column;
343
+ align-items: center;
344
+ justify-content: center;
345
+ min-height: 128px;
346
+ text-align: center;
347
+ font-size: 0;
348
+ overflow: hidden;
349
+ border: 1px solid rgba(255, 255, 255, 0.2);
350
+ border-radius: 8px;
351
+ background: rgba(255, 255, 255, 0.05);
352
+ cursor: pointer;
353
+ transition: border-color 0.2s ease;
354
+ }
355
+
356
+ .taskon-pow-image-upload-area:hover:not(.taskon-pow-image-upload-area--disabled) {
357
+ border-color: var(--taskon-primary-color, #3b82f6);
358
+ }
359
+
360
+ .taskon-pow-image-upload-area:focus {
361
+ outline: none;
362
+ border-color: var(--taskon-primary-color, #3b82f6);
363
+ }
364
+
365
+ .taskon-pow-image-upload-area--disabled {
366
+ opacity: 0.5;
367
+ cursor: not-allowed;
368
+ }
369
+
370
+ .taskon-pow-image-upload-icon {
371
+ width: 18px;
372
+ height: 18px;
373
+ color: rgba(255, 255, 255, 0.6);
374
+ }
375
+
376
+ .taskon-pow-image-upload-tip {
377
+ margin-top: 13px;
378
+ font-size: 14px;
379
+ line-height: 20px;
380
+ letter-spacing: 0.04em;
381
+ text-transform: uppercase;
382
+ white-space: pre-wrap;
383
+ color: rgba(255, 255, 255, 0.6);
384
+ }
385
+
386
+ .taskon-pow-image-preview {
387
+ border-radius: 4px;
388
+ margin: 20px 0;
389
+ max-width: 100%;
390
+ max-height: 300px;
391
+ }
392
+
393
+ /* Hover mask overlay */
394
+ .taskon-pow-image-mask {
395
+ display: none;
396
+ position: absolute;
397
+ inset: 0;
398
+ z-index: 2;
399
+ align-items: center;
400
+ justify-content: center;
401
+ flex-direction: column;
402
+ background: rgba(0, 0, 0, 0.8);
403
+ }
404
+
405
+ .taskon-pow-image-upload-area:hover .taskon-pow-image-mask,
406
+ .taskon-pow-image-upload-area:focus .taskon-pow-image-mask {
407
+ display: flex;
408
+ }
409
+
410
+ .taskon-pow-image-mask .taskon-pow-image-upload-icon {
411
+ color: #fff;
412
+ }
413
+
414
+ .taskon-pow-image-mask .taskon-pow-image-upload-tip {
415
+ color: #fff;
416
+ opacity: 1;
417
+ }
418
+
419
+ /* Progress bar at bottom */
420
+ .taskon-pow-image-progress-bar {
421
+ z-index: 3;
422
+ position: absolute;
423
+ right: 0;
424
+ bottom: 0;
425
+ left: 0;
426
+ background: rgba(255, 255, 255, 0.1);
427
+ height: 6px;
428
+ }
429
+
430
+ .taskon-pow-image-progress-fill {
431
+ background: var(--taskon-primary-color, #3b82f6);
432
+ height: 100%;
433
+ border-radius: 4px;
434
+ transition: width 0.2s ease;
435
+ }
436
+
437
+ /* ============================================
438
+ * Error Message
439
+ * ============================================ */
440
+ .taskon-pow-error {
441
+ margin-top: 10px;
442
+ font-size: 14px;
443
+ color: #ef4444;
444
+ }
445
+
446
+ /* ============================================
447
+ * Average Review Time
448
+ * ============================================ */
449
+ /* 与 Vue 版本 AverageReview.vue 样式一致 */
450
+ .taskon-pow-review-time {
451
+ margin-top: 10px;
452
+ color: rgba(255, 212, 101, 0.6);
453
+ font-size: 13px;
454
+ font-weight: 500;
455
+ line-height: 16px;
456
+ }
457
+
458
+ /* ============================================
459
+ * Responsive Styles
460
+ * ============================================ */
461
+ @media (max-width: 750px) {
462
+ .taskon-pow-url-row,
463
+ .taskon-pow-text-row {
464
+ flex-direction: column;
465
+ gap: 10px;
466
+ }
467
+
468
+ .taskon-pow-input {
469
+ width: 100%;
470
+ }
471
+
472
+ .taskon-pow-url-row .taskon-verify-btn,
473
+ .taskon-pow-text-row .taskon-verify-btn {
474
+ width: 100%;
475
+ }
476
+
477
+ .taskon-pow-image-uploader {
478
+ margin-top: 2.67vw;
479
+ }
480
+
481
+ .taskon-pow-image-upload-area {
482
+ min-height: 17.07vw;
483
+ }
484
+
485
+ .taskon-pow-image-upload-icon {
486
+ width: 2.4vw;
487
+ height: 2.4vw;
488
+ }
489
+
490
+ .taskon-pow-image-upload-tip {
491
+ margin-top: 1.33vw;
492
+ font-size: 1.6vw;
493
+ line-height: 2.67vw;
494
+ }
495
+
496
+ .taskon-pow-image-preview {
497
+ max-height: 32vw;
498
+ }
499
+ }
500
+ /**
501
+ * ContractInteractiveTask Styles
502
+ */
503
+
504
+ .taskon-contract-task {
505
+ /* 继承 TaskCardBase 样式 */
506
+ }
507
+
508
+ .taskon-contract-desc {
509
+ font-size: 14px;
510
+ line-height: 21px;
511
+ color: rgba(255, 255, 255, 0.8);
512
+ word-break: break-word;
513
+ }
514
+
515
+ .taskon-contract-desc a {
516
+ color: var(--taskon-primary-color, #3b82f6);
517
+ text-decoration: none;
518
+ }
519
+
520
+ .taskon-contract-desc a:hover {
521
+ text-decoration: underline;
522
+ }
523
+ /* ============================================
524
+ DynamicPoints Component Styles
525
+ 与 Vue 版本 BaseDynamicPoint.vue 样式一致
526
+ ============================================ */
527
+
528
+ .taskon-dynamic-points {
529
+ display: inline-flex;
530
+ align-items: center;
531
+ gap: 8px;
532
+ padding: 8px 12px;
533
+ background: rgba(255, 255, 255, 0.04);
534
+ border-radius: 8px;
535
+ }
536
+
537
+ .taskon-dynamic-points-value-wrap {
538
+ display: flex;
539
+ align-items: center;
540
+ gap: 8px;
541
+ flex-shrink: 0;
542
+ }
543
+
544
+ .taskon-dynamic-points-value {
545
+ font-size: 16px;
546
+ font-weight: 600;
547
+ color: var(--taskon-task-text-primary, #fff);
548
+ }
549
+
550
+ .taskon-dynamic-points-value--highlight {
551
+ color: #00ffa3 !important;
552
+ }
553
+
554
+ .taskon-dynamic-points-max {
555
+ font-size: 14px;
556
+ font-weight: 500;
557
+ color: var(--taskon-task-text-secondary, rgba(255, 255, 255, 0.6));
558
+ text-transform: capitalize;
559
+ }
560
+
561
+ .taskon-dynamic-points-info {
562
+ display: inline-flex;
563
+ align-items: center;
564
+ justify-content: center;
565
+ color: var(--taskon-task-text-secondary, rgba(255, 255, 255, 0.6));
566
+ cursor: pointer;
567
+ }
568
+
569
+ .taskon-dynamic-points-info:hover {
570
+ color: var(--taskon-task-text-primary, #fff);
571
+ }
572
+
573
+ .taskon-dynamic-points-refresh {
574
+ display: inline-flex;
575
+ align-items: center;
576
+ justify-content: center;
577
+ width: 24px;
578
+ height: 24px;
579
+ padding: 0;
580
+ margin-left: 4px;
581
+ background: transparent;
582
+ border: none;
583
+ border-radius: 4px;
584
+ color: #54aeff;
585
+ cursor: pointer;
586
+ transition: opacity 0.2s, transform 0.2s;
587
+ }
588
+
589
+ .taskon-dynamic-points-refresh:hover:not(:disabled) {
590
+ opacity: 0.8;
591
+ }
592
+
593
+ .taskon-dynamic-points-refresh--disabled {
594
+ opacity: 0.6;
595
+ cursor: not-allowed;
596
+ }
597
+
598
+ .taskon-dynamic-points-refresh--animating {
599
+ filter: drop-shadow(0 0 4px rgba(84, 174, 255, 0.8));
600
+ }
601
+
602
+ .taskon-dynamic-points-refresh-icon {
603
+ width: 16px;
604
+ height: 16px;
605
+ }
606
+
607
+ .taskon-dynamic-points-refresh-icon--spin {
608
+ animation: taskon-spin 1s linear infinite;
609
+ }
610
+
611
+ @keyframes taskon-spin {
612
+ from {
613
+ transform: rotate(0deg);
614
+ }
615
+ to {
616
+ transform: rotate(360deg);
617
+ }
618
+ }
619
+
620
+ .taskon-dynamic-points-cooldown {
621
+ font-size: 14px;
622
+ font-weight: 500;
623
+ color: #54aeff !important;
624
+ font-family: Menlo, Consolas, "Liberation Mono", "Courier New", Courier, monospace;
625
+ }
626
+ /**
627
+ * SwapDexTask Styles
628
+ * 与原版 Vue SwapDexContractInteractive + SwapDexVolumeRules 样式一致
629
+ */
630
+
631
+ .taskon-swap-task {
632
+ /* 继承 TaskCardBase 样式 */
633
+ }
634
+
635
+ /* Content wrapper */
636
+ .taskon-swap-content {
637
+ display: flex;
638
+ flex-direction: column;
639
+ gap: 16px;
640
+ }
641
+
642
+ /* Rules section - 动态积分规则区域 */
643
+ .taskon-swap-rules-section {
644
+ display: flex;
645
+ flex-direction: column;
646
+ gap: 8px;
647
+ }
648
+
649
+ .taskon-swap-rules-title {
650
+ font-size: 14px;
651
+ font-weight: 500;
652
+ color: rgba(255, 255, 255, 0.6);
653
+ margin-bottom: 8px;
654
+ }
655
+
656
+ .taskon-swap-rules-content {
657
+ display: flex;
658
+ flex-wrap: wrap;
659
+ align-items: center;
660
+ gap: 4px;
661
+ padding: 12px;
662
+ border-radius: 8px;
663
+ background: rgba(255, 255, 255, 0.05);
664
+ font-size: 14px;
665
+ font-weight: 500;
666
+ color: rgba(255, 255, 255, 0.6);
667
+ }
668
+
669
+ .taskon-swap-rules-highlight {
670
+ color: var(--taskon-secondary-color, #00ffa3);
671
+ }
672
+
673
+ .taskon-swap-rules-point-name {
674
+ color: rgba(255, 255, 255, 0.4);
675
+ }
676
+
677
+ /* Instructions section - 任务描述区域 */
678
+ .taskon-swap-instructions-section {
679
+ display: flex;
680
+ flex-direction: column;
681
+ gap: 8px;
682
+ }
683
+
684
+ .taskon-swap-instructions-title {
685
+ font-size: 14px;
686
+ font-weight: 500;
687
+ color: rgba(255, 255, 255, 0.6);
688
+ margin-bottom: 8px;
689
+ }
690
+
691
+ .taskon-swap-instructions-content {
692
+ padding: 12px;
693
+ border-radius: 8px;
694
+ background: rgba(255, 255, 255, 0.05);
695
+ }
696
+
697
+ .taskon-swap-desc {
698
+ font-size: 14px;
699
+ line-height: 21px;
700
+ color: rgba(255, 255, 255, 0.8);
701
+ word-break: break-word;
702
+ }
703
+
704
+ .taskon-swap-desc a {
705
+ color: var(--taskon-primary-color, #3b82f6);
706
+ text-decoration: none;
707
+ }
708
+
709
+ .taskon-swap-desc a:hover {
710
+ text-decoration: underline;
711
+ }
712
+ /**
713
+ * OuterPointAPITask Styles
714
+ * 与 Vue 版本 OuterPointVerify + CustomizedSubmitDialog 样式一致
715
+ */
716
+
717
+ .taskon-outer-point-api-task {
718
+ /* 继承 TaskCardBase 样式 */
719
+ }
720
+
721
+ /* ==================== Description Area ==================== */
722
+ .taskon-outer-point-api-desc {
723
+ font-size: 14px;
724
+ line-height: 21px;
725
+ color: rgba(255, 255, 255, 0.8);
726
+ word-break: break-word;
727
+ }
728
+
729
+ .taskon-outer-point-api-desc a {
730
+ color: var(--taskon-primary-color, #3b82f6);
731
+ text-decoration: none;
732
+ }
733
+
734
+ .taskon-outer-point-api-desc a:hover {
735
+ text-decoration: underline;
736
+ }
737
+
738
+ /* ==================== Customized Param Dialog ==================== */
739
+ .taskon-outer-point-api-dialog {
740
+ display: flex;
741
+ flex-direction: column;
742
+ gap: 16px;
743
+ }
744
+
745
+ /* Dialog title */
746
+ .taskon-outer-point-api-dialog-title {
747
+ font-size: 18px;
748
+ font-weight: 600;
749
+ color: #fff;
750
+ margin: 0;
751
+ }
752
+
753
+ /* Warning message */
754
+ .taskon-outer-point-api-dialog-warning {
755
+ display: flex;
756
+ align-items: center;
757
+ gap: 8px;
758
+ padding: 12px;
759
+ border-radius: 8px;
760
+ background: rgba(255, 171, 0, 0.1);
761
+ color: #ffab00;
762
+ font-size: 14px;
763
+ line-height: 20px;
764
+ }
765
+
766
+ .taskon-outer-point-api-dialog-warning-icon {
767
+ flex-shrink: 0;
768
+ width: 20px;
769
+ height: 20px;
770
+ }
771
+
772
+ /* Description text */
773
+ .taskon-outer-point-api-dialog-desc {
774
+ font-size: 14px;
775
+ line-height: 20px;
776
+ color: rgba(255, 255, 255, 0.6);
777
+ }
778
+
779
+ /* Input area */
780
+ .taskon-outer-point-api-dialog-input-wrap {
781
+ display: flex;
782
+ flex-direction: column;
783
+ gap: 8px;
784
+ }
785
+
786
+ .taskon-outer-point-api-dialog-label {
787
+ font-size: 14px;
788
+ font-weight: 500;
789
+ color: rgba(255, 255, 255, 0.8);
790
+ }
791
+
792
+ .taskon-outer-point-api-dialog-input {
793
+ width: 100%;
794
+ padding: 10px 12px;
795
+ border-radius: 8px;
796
+ border: 1px solid rgba(255, 255, 255, 0.15);
797
+ background: rgba(255, 255, 255, 0.05);
798
+ color: #fff;
799
+ font-size: 14px;
800
+ line-height: 20px;
801
+ outline: none;
802
+ transition: border-color 0.2s ease;
803
+ box-sizing: border-box;
804
+ }
805
+
806
+ .taskon-outer-point-api-dialog-input::placeholder {
807
+ color: rgba(255, 255, 255, 0.3);
808
+ }
809
+
810
+ .taskon-outer-point-api-dialog-input:focus {
811
+ border-color: var(--taskon-primary-color, #3b82f6);
812
+ }
813
+
814
+ .taskon-outer-point-api-dialog-input--error {
815
+ border-color: #ff4d4f;
816
+ }
817
+
818
+ .taskon-outer-point-api-dialog-error {
819
+ font-size: 12px;
820
+ color: #ff4d4f;
821
+ }
822
+
823
+ /* Action buttons */
824
+ .taskon-outer-point-api-dialog-actions {
825
+ display: flex;
826
+ justify-content: flex-end;
827
+ gap: 12px;
828
+ margin-top: 8px;
829
+ }
830
+
831
+ .taskon-outer-point-api-dialog-btn {
832
+ padding: 8px 24px;
833
+ border-radius: 8px;
834
+ font-size: 14px;
835
+ font-weight: 500;
836
+ cursor: pointer;
837
+ transition: all 0.2s ease;
838
+ border: none;
839
+ }
840
+
841
+ .taskon-outer-point-api-dialog-btn--cancel {
842
+ background: rgba(255, 255, 255, 0.1);
843
+ color: rgba(255, 255, 255, 0.8);
844
+ }
845
+
846
+ .taskon-outer-point-api-dialog-btn--cancel:hover {
847
+ background: rgba(255, 255, 255, 0.15);
848
+ }
849
+
850
+ .taskon-outer-point-api-dialog-btn--confirm {
851
+ background: var(--taskon-primary-color, #3b82f6);
852
+ color: #fff;
853
+ }
854
+
855
+ .taskon-outer-point-api-dialog-btn--confirm:hover {
856
+ opacity: 0.9;
857
+ }
858
+
859
+ .taskon-outer-point-api-dialog-btn--confirm:disabled {
860
+ opacity: 0.5;
861
+ cursor: not-allowed;
862
+ }
863
+ /**
864
+ * TaskWidget Styles
865
+ * @description 任务列表组件样式(与 taskon-website BaseTask.vue 保持一致)
866
+ *
867
+ * 命名规范:.taskon-task-{component}-{element}--{modifier}
868
+ */
869
+
870
+ /* ============================================
871
+ CSS Variables (可被项目方覆盖)
872
+ ============================================ */
873
+ :root {
874
+ /* Task card colors (dark theme, same as taskon-website) */
875
+ --taskon-task-bg: #1d2123;
876
+ --taskon-task-border: #1d2123;
877
+ --taskon-task-border-hover: #41494b;
878
+ --taskon-task-radius: 10px;
879
+
880
+ /* Text colors */
881
+ --taskon-task-text: #ffffff;
882
+ --taskon-task-text-secondary: #9ca3af;
883
+ --taskon-task-text-muted: #6b7280;
884
+
885
+ /* Status colors */
886
+ --taskon-color-primary: #3b82f6;
887
+ --taskon-color-success: #22c55e;
888
+ --taskon-color-warning: #f59e0b;
889
+ --taskon-color-error: #ef4444;
890
+
891
+ /* Recurrence badge color */
892
+ --taskon-recurrence-color: #9aff73;
893
+
894
+ /* Spacing */
895
+ --taskon-task-spacing-xs: 4px;
896
+ --taskon-task-spacing-sm: 8px;
897
+ --taskon-task-spacing-md: 12px;
898
+ --taskon-task-spacing-lg: 16px;
899
+ --taskon-task-spacing-xl: 24px;
900
+
901
+ /* Transitions */
902
+ --taskon-task-transition: 0.2s ease;
903
+ }
904
+
905
+ /* ============================================
906
+ TaskList Styles
907
+ 与 Vue 版本 TaskList.vue + TaskType.vue 一致
908
+ ============================================ */
909
+ .taskon-task-list {
910
+ display: flex;
911
+ flex-direction: column;
912
+ gap: var(--taskon-task-spacing-lg);
913
+ }
914
+
915
+ /* Progress section */
916
+ .taskon-task-list-progress-wrap {
917
+ margin-bottom: var(--taskon-task-spacing-sm);
918
+ }
919
+
920
+ /* Section styles */
921
+ .taskon-task-list-section {
922
+ display: flex;
923
+ flex-direction: column;
924
+ }
925
+
926
+ .taskon-task-list-section-header {
927
+ display: flex;
928
+ justify-content: space-between;
929
+ align-items: center;
930
+ margin-top: 30px;
931
+ margin-bottom: 22px;
932
+ }
933
+
934
+ .taskon-task-list-section-label {
935
+ display: flex;
936
+ align-items: center;
937
+ gap: 6px;
938
+ }
939
+
940
+ .taskon-task-list-section-title {
941
+ font-size: 22px;
942
+ font-weight: 600;
943
+ line-height: 21px;
944
+ color: var(--taskon-task-text);
945
+ }
946
+
947
+ .taskon-task-list-section-hint {
948
+ font-size: 14px;
949
+ color: rgba(255, 255, 255, 0.6);
950
+ }
951
+
952
+ .taskon-task-list-section-hint-em {
953
+ font-weight: 600;
954
+ color: rgba(0, 255, 163, 1);
955
+ }
956
+
957
+ .taskon-task-list-items {
958
+ display: flex;
959
+ flex-direction: column;
960
+ gap: 20px;
961
+ }
962
+
963
+ /* First section header doesn't need top margin */
964
+ .taskon-task-list-section:first-child .taskon-task-list-section-header {
965
+ margin-top: 0;
966
+ }
967
+
968
+ /* Empty state */
969
+ .taskon-task-list-empty {
970
+ padding: var(--taskon-task-spacing-xl);
971
+ text-align: center;
972
+ color: var(--taskon-task-text-muted);
973
+ }
974
+
975
+ /* Mobile responsive */
976
+ @media (max-width: 750px) {
977
+ .taskon-task-list-section-header {
978
+ display: block;
979
+ margin-top: 5.6vw;
980
+ margin-bottom: 4vw;
981
+ }
982
+
983
+ .taskon-task-list-section-label {
984
+ flex-wrap: wrap;
985
+ gap: 1.6vw;
986
+ }
987
+
988
+ .taskon-task-list-section-title {
989
+ font-size: 4.8vw;
990
+ line-height: 6vw;
991
+ }
992
+
993
+ .taskon-completed-count {
994
+ margin-top: 2.67vw;
995
+ justify-content: flex-start;
996
+ }
997
+
998
+ .taskon-completed-count-check {
999
+ width: 3.2vw;
1000
+ height: 2.4vw;
1001
+ margin-right: 2.13vw;
1002
+ }
1003
+
1004
+ .taskon-completed-count-text {
1005
+ font-size: 3.47vw;
1006
+ line-height: 4.4vw;
1007
+ }
1008
+
1009
+ .taskon-task-list-items {
1010
+ gap: 3.07vw;
1011
+ }
1012
+ }
1013
+
1014
+ /* ============================================
1015
+ TaskProgress Styles
1016
+ ============================================ */
1017
+ .taskon-task-progress {
1018
+ display: flex;
1019
+ flex-direction: column;
1020
+ gap: var(--taskon-task-spacing-sm);
1021
+ }
1022
+
1023
+ .taskon-task-progress-bar {
1024
+ height: 6px;
1025
+ background: rgba(255, 255, 255, 0.1);
1026
+ border-radius: 3px;
1027
+ overflow: hidden;
1028
+ }
1029
+
1030
+ .taskon-task-progress-bar-fill {
1031
+ height: 100%;
1032
+ background: var(--taskon-color-primary);
1033
+ border-radius: 3px;
1034
+ transition: width var(--taskon-task-transition);
1035
+ }
1036
+
1037
+ .taskon-task-progress--completed .taskon-task-progress-bar-fill {
1038
+ background: var(--taskon-color-success);
1039
+ }
1040
+
1041
+ .taskon-task-progress-text {
1042
+ display: flex;
1043
+ align-items: center;
1044
+ gap: var(--taskon-task-spacing-xs);
1045
+ font-size: 13px;
1046
+ color: var(--taskon-task-text-secondary);
1047
+ }
1048
+
1049
+ .taskon-task-progress--completed .taskon-task-progress-text {
1050
+ color: var(--taskon-color-success);
1051
+ }
1052
+
1053
+ .taskon-task-progress-icon {
1054
+ display: inline-flex;
1055
+ align-items: center;
1056
+ justify-content: center;
1057
+ }
1058
+
1059
+ /* ============================================
1060
+ TaskItem Styles
1061
+ ============================================ */
1062
+ .taskon-task-item {
1063
+ position: relative;
1064
+ padding: 16px 20px;
1065
+ background: var(--taskon-task-bg);
1066
+ border-radius: var(--taskon-task-radius);
1067
+ border: 1px solid var(--taskon-task-border);
1068
+ transition: border-color var(--taskon-task-transition);
1069
+ }
1070
+
1071
+ .taskon-task-item:hover {
1072
+ border-color: var(--taskon-task-border-hover);
1073
+ }
1074
+
1075
+ /* ============================================
1076
+ 左上角浮标:周期标签 / 冷却倒计时
1077
+ 与 Vue 版本 RecurrenceStatus.vue 样式一致
1078
+ ============================================ */
1079
+ .taskon-task-item-recurrence {
1080
+ position: absolute;
1081
+ top: -6px;
1082
+ left: 12px;
1083
+ /* 与 Vue 版本一致:使用 SVG 背景 */
1084
+ background: url("data:image/svg+xml,%3csvg%20width='69'%20height='20'%20viewBox='0%200%2069%2020'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20filter='url(%23filter0_i_10913_141293)'%3e%3cpath%20d='M67.9996%204.5C67.9996%202.5%2066.7705%201%2064.1369%201H3.42655C0.791465%201%200%203%200%204.64199L67.9996%204.5Z'%20fill='%2328491F'/%3e%3c/g%3e%3cg%20filter='url(%23filter1_d_10913_141293)'%3e%3cpath%20d='M2.99902%201H11.242H65.999V1C64.6983%201%2063.6439%202.05443%2063.6439%203.35514V13C63.6439%2015.2091%2061.853%2017%2059.6439%2017H11.1205C8.91138%2017%207.12052%2015.2091%207.12052%2013V5.1215C7.12052%202.84526%205.27526%201%202.99902%201V1Z'%20fill='%232D422A'/%3e%3c/g%3e%3cdefs%3e%3cfilter%20id='filter0_i_10913_141293'%20x='0'%20y='1'%20width='67.9996'%20height='4.64197'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='BackgroundImageFix'%20result='shape'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dy='1'/%3e%3cfeGaussianBlur%20stdDeviation='4.1'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='arithmetic'%20k2='-1'%20k3='1'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.8%200'/%3e%3cfeBlend%20mode='normal'%20in2='shape'%20result='effect1_innerShadow_10913_141293'/%3e%3c/filter%3e%3cfilter%20id='filter1_d_10913_141293'%20x='1.99902'%20y='0'%20width='67'%20height='20'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dx='1'%20dy='1'/%3e%3cfeGaussianBlur%20stdDeviation='1'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='out'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.25%200'/%3e%3cfeBlend%20mode='normal'%20in2='BackgroundImageFix'%20result='effect1_dropShadow_10913_141293'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='effect1_dropShadow_10913_141293'%20result='shape'/%3e%3c/filter%3e%3c/defs%3e%3c/svg%3e") no-repeat center center;
1085
+ background-size: cover;
1086
+ /* 固定尺寸与 Vue 版本一致 */
1087
+ width: 78px;
1088
+ height: 20px;
1089
+ /* 文字样式 */
1090
+ color: var(--taskon-recurrence-color);
1091
+ font-size: 12px;
1092
+ line-height: 16px;
1093
+ font-weight: 500;
1094
+ text-align: center;
1095
+ display: flex;
1096
+ align-items: center;
1097
+ justify-content: center;
1098
+ }
1099
+
1100
+ /* 冷却倒计时样式 - 继承标签样式 */
1101
+ .taskon-task-item-recurrence .taskon-cooldown-timer {
1102
+ color: var(--taskon-recurrence-color);
1103
+ font-size: 12px;
1104
+ line-height: 16px;
1105
+ font-weight: 500;
1106
+ }
1107
+
1108
+ /* ============================================
1109
+ 第一行:图标 + 标题 + 右侧内容
1110
+ ============================================ */
1111
+ .taskon-task-item-row {
1112
+ display: flex;
1113
+ align-items: center;
1114
+ }
1115
+
1116
+ /* Left section: Icon + Title */
1117
+ .taskon-task-item-left {
1118
+ display: flex;
1119
+ align-items: center;
1120
+ flex: 1;
1121
+ min-width: 0;
1122
+ }
1123
+
1124
+ .taskon-task-item-icon {
1125
+ flex-shrink: 0;
1126
+ display: flex;
1127
+ align-items: center;
1128
+ justify-content: center;
1129
+ margin-right: 16px;
1130
+ color: var(--taskon-task-text-secondary);
1131
+ }
1132
+
1133
+ .taskon-task-item--completed .taskon-task-item-icon {
1134
+ color: var(--taskon-color-success);
1135
+ }
1136
+
1137
+ /* Title wrapper - 与 Vue 版本 TitleRow 结构一致 */
1138
+ /* 普通 block flow,标题 inline,TotalEarnPoint 作为 block div 自然换行 */
1139
+ .taskon-task-item-title-wrap {
1140
+ flex: 1;
1141
+ min-width: 0;
1142
+ }
1143
+
1144
+ .taskon-task-item-title {
1145
+ display: inline;
1146
+ font-size: 18px;
1147
+ font-weight: 500;
1148
+ color: var(--taskon-task-text);
1149
+ line-height: 23px;
1150
+ overflow-wrap: break-word;
1151
+ }
1152
+
1153
+ /* Title as link - 参考 Vue 版本 TitleRow.vue 的 OutLink 样式 */
1154
+ .taskon-task-item-title--link {
1155
+ color: #54aeff;
1156
+ text-decoration: underline;
1157
+ transition: opacity var(--taskon-task-transition);
1158
+ }
1159
+
1160
+ .taskon-task-item-title--link:hover {
1161
+ opacity: 0.8;
1162
+ }
1163
+
1164
+ .taskon-task-item--completed .taskon-task-item-title {
1165
+ color: var(--taskon-task-text-secondary);
1166
+ }
1167
+
1168
+ /* Links in title - 统一蓝色加下划线样式 */
1169
+ .taskon-task-item-link {
1170
+ color: #54aeff;
1171
+ text-decoration: underline;
1172
+ transition: opacity var(--taskon-task-transition);
1173
+ }
1174
+
1175
+ .taskon-task-item-link:hover {
1176
+ opacity: 0.8;
1177
+ }
1178
+
1179
+ /* Title tip icon */
1180
+ .taskon-task-item-title-tip {
1181
+ display: inline-flex;
1182
+ align-items: center;
1183
+ justify-content: center;
1184
+ margin-left: 6px;
1185
+ color: rgba(255, 255, 255, 0.4);
1186
+ cursor: help;
1187
+ flex-shrink: 0;
1188
+ }
1189
+
1190
+ .taskon-task-item-title-tip:hover {
1191
+ color: rgba(255, 255, 255, 0.6);
1192
+ }
1193
+
1194
+ /* Right section: Points + Total + Verify */
1195
+ .taskon-task-item-right {
1196
+ display: flex;
1197
+ align-items: center;
1198
+ gap: var(--taskon-task-spacing-md);
1199
+ flex-shrink: 0;
1200
+ margin-left: 10px;
1201
+ }
1202
+
1203
+ /* Points display - 参考 TaskPoint.vue */
1204
+ .taskon-task-item-points {
1205
+ min-width: 40px;
1206
+ height: 34px;
1207
+ padding: 0 10px;
1208
+ display: flex;
1209
+ align-items: center;
1210
+ justify-content: center;
1211
+ gap: 2px;
1212
+ background: rgba(255, 255, 255, 0.04);
1213
+ border-radius: 6px;
1214
+ font-size: 16px;
1215
+ font-weight: 500;
1216
+ }
1217
+
1218
+ .taskon-task-item-points-value {
1219
+ color: #ffffff;
1220
+ }
1221
+
1222
+ /* Points value when task is completed - green color like Vue version */
1223
+ .taskon-task-item-points-value--completed {
1224
+ color: #00ffa3;
1225
+ }
1226
+
1227
+ .taskon-task-item-points-time {
1228
+ font-size: 12px;
1229
+ color: rgba(255, 255, 255, 0.6);
1230
+ }
1231
+
1232
+ /* Tip icon next to points (margin controlled externally) */
1233
+ .taskon-task-item-tip {
1234
+ margin-left: 10px;
1235
+ }
1236
+
1237
+ /* Total points */
1238
+ .taskon-task-item-total-points {
1239
+ font-size: 12px;
1240
+ color: var(--taskon-task-text-muted);
1241
+ }
1242
+
1243
+ /* ============================================
1244
+ TotalEarnPoint Styles
1245
+ 与 Vue 版本 TotalEarnPoint.vue 样式一致
1246
+ ============================================ */
1247
+ .taskon-task-item-total-earn {
1248
+ display: flex;
1249
+ align-items: center;
1250
+ }
1251
+
1252
+ .taskon-task-item-total-earn-text {
1253
+ color: rgba(255, 255, 255, 0.6);
1254
+ font-size: 14px;
1255
+ }
1256
+
1257
+ .taskon-task-item-total-earn-value {
1258
+ color: #9aff73;
1259
+ font-size: 14px;
1260
+ margin: 0 4px;
1261
+ }
1262
+
1263
+ /* ============================================
1264
+ 第二行:内容区域(始终显示)
1265
+ ============================================ */
1266
+ .taskon-task-item-body {
1267
+ margin-left: 50px;
1268
+ margin-top: 10px;
1269
+ }
1270
+
1271
+ .taskon-task-item-content {
1272
+ display: flex;
1273
+ flex-direction: column;
1274
+ gap: var(--taskon-task-spacing-md);
1275
+ }
1276
+
1277
+ .taskon-task-item-desc {
1278
+ font-size: 14px;
1279
+ line-height: 21px;
1280
+ color: var(--taskon-task-text-secondary);
1281
+ word-break: break-all;
1282
+ white-space: pre-wrap;
1283
+ }
1284
+
1285
+ .taskon-task-item-desc span {
1286
+ color: var(--taskon-task-text);
1287
+ word-break: break-all;
1288
+ }
1289
+
1290
+ /* Rich text content - 参考 Vue 版本 TextPreview.vue */
1291
+ .taskon-task-item-rich-text {
1292
+ font-size: 14px;
1293
+ line-height: 21px;
1294
+ color: var(--taskon-task-text-secondary);
1295
+ word-break: break-word;
1296
+ }
1297
+
1298
+ .taskon-task-item-rich-text p {
1299
+ margin: 0 0 0.5em 0;
1300
+ }
1301
+
1302
+ .taskon-task-item-rich-text p:last-child {
1303
+ margin-bottom: 0;
1304
+ }
1305
+
1306
+ .taskon-task-item-rich-text a {
1307
+ color: #54aeff;
1308
+ text-decoration: underline;
1309
+ }
1310
+
1311
+ .taskon-task-item-rich-text a:hover {
1312
+ opacity: 0.8;
1313
+ }
1314
+
1315
+ .taskon-task-item-rich-text strong,
1316
+ .taskon-task-item-rich-text b {
1317
+ font-weight: 600;
1318
+ color: var(--taskon-task-text);
1319
+ }
1320
+
1321
+ .taskon-task-item-rich-text em,
1322
+ .taskon-task-item-rich-text i {
1323
+ font-style: italic;
1324
+ }
1325
+
1326
+ .taskon-task-item-rich-text ul,
1327
+ .taskon-task-item-rich-text ol {
1328
+ margin: 0.5em 0;
1329
+ padding-left: 1.5em;
1330
+ }
1331
+
1332
+ .taskon-task-item-rich-text li {
1333
+ margin: 0.25em 0;
1334
+ }
1335
+
1336
+ .taskon-task-item-rich-text code {
1337
+ background: rgba(255, 255, 255, 0.1);
1338
+ padding: 0.2em 0.4em;
1339
+ border-radius: 3px;
1340
+ font-size: 0.9em;
1341
+ }
1342
+
1343
+ .taskon-task-item-rich-text pre {
1344
+ background: rgba(255, 255, 255, 0.05);
1345
+ padding: 0.75em 1em;
1346
+ border-radius: 6px;
1347
+ overflow-x: auto;
1348
+ margin: 0.5em 0;
1349
+ }
1350
+
1351
+ .taskon-task-item-rich-text blockquote {
1352
+ border-left: 3px solid var(--taskon-color-primary);
1353
+ padding-left: 1em;
1354
+ margin: 0.5em 0;
1355
+ color: var(--taskon-task-text-muted);
1356
+ }
1357
+
1358
+ .taskon-task-item-rich-text img {
1359
+ max-width: 100%;
1360
+ height: auto;
1361
+ border-radius: 6px;
1362
+ }
1363
+
1364
+ /* Description fields */
1365
+ .taskon-task-item-fields {
1366
+ display: flex;
1367
+ flex-direction: column;
1368
+ gap: var(--taskon-task-spacing-xs);
1369
+ }
1370
+
1371
+ .taskon-task-item-field {
1372
+ display: flex;
1373
+ align-items: baseline;
1374
+ gap: var(--taskon-task-spacing-sm);
1375
+ font-size: 13px;
1376
+ }
1377
+
1378
+ .taskon-task-item-field-key {
1379
+ color: var(--taskon-task-text-muted);
1380
+ flex-shrink: 0;
1381
+ }
1382
+
1383
+ .taskon-task-item-field-value {
1384
+ color: var(--taskon-task-text);
1385
+ word-break: break-all;
1386
+ }
1387
+
1388
+ .taskon-task-item-field-value--link {
1389
+ color: #54aeff;
1390
+ text-decoration: underline;
1391
+ transition: opacity var(--taskon-task-transition);
1392
+ }
1393
+
1394
+ .taskon-task-item-field-value--link:hover {
1395
+ opacity: 0.8;
1396
+ }
1397
+
1398
+ /* Action link */
1399
+ .taskon-task-item-action-link {
1400
+ display: inline-flex;
1401
+ align-items: center;
1402
+ padding: var(--taskon-task-spacing-sm) var(--taskon-task-spacing-md);
1403
+ font-size: 13px;
1404
+ font-weight: 500;
1405
+ color: var(--taskon-color-primary);
1406
+ background: transparent;
1407
+ border: 1px solid var(--taskon-color-primary);
1408
+ border-radius: 6px;
1409
+ text-decoration: none;
1410
+ transition: all var(--taskon-task-transition);
1411
+ align-self: flex-start;
1412
+ }
1413
+
1414
+ .taskon-task-item-action-link:hover {
1415
+ background: var(--taskon-color-primary);
1416
+ color: white;
1417
+ }
1418
+
1419
+ /* Spinner animation */
1420
+ @keyframes taskon-spin {
1421
+ from {
1422
+ transform: rotate(0deg);
1423
+ }
1424
+ to {
1425
+ transform: rotate(360deg);
1426
+ }
1427
+ }
1428
+
1429
+ .taskon-task-item-spinner {
1430
+ animation: taskon-spin 1s linear infinite;
1431
+ }
1432
+
1433
+ /* ============================================
1434
+ TaskIcon Styles
1435
+ ============================================ */
1436
+ .taskon-task-icon {
1437
+ display: inline-flex;
1438
+ align-items: center;
1439
+ justify-content: center;
1440
+ flex-shrink: 0;
1441
+ }
1442
+
1443
+ .taskon-task-icon-img {
1444
+ border-radius: 50%;
1445
+ object-fit: cover;
1446
+ }
1447
+
1448
+ /* ============================================
1449
+ CooldownTimer Styles
1450
+ ============================================ */
1451
+ .taskon-cooldown-timer {
1452
+ display: inline-flex;
1453
+ align-items: center;
1454
+ gap: var(--taskon-task-spacing-xs);
1455
+ font-size: 13px;
1456
+ color: var(--taskon-color-warning);
1457
+ }
1458
+
1459
+ /* ============================================
1460
+ VerifyButton Styles
1461
+ ============================================ */
1462
+ .taskon-verify-btn {
1463
+ display: inline-flex;
1464
+ align-items: center;
1465
+ justify-content: center;
1466
+ gap: 4px;
1467
+ height: 34px;
1468
+ padding: 0 12px;
1469
+ font-size: 14px;
1470
+ font-weight: 500;
1471
+ line-height: 20px;
1472
+ color: #fff;
1473
+ background: transparent;
1474
+ border: 1px solid rgba(255, 255, 255, 0.1);
1475
+ border-radius: 6px;
1476
+ cursor: pointer;
1477
+ transition: all var(--taskon-task-transition);
1478
+ white-space: nowrap;
1479
+ flex-shrink: 0;
1480
+ }
1481
+
1482
+ .taskon-verify-btn:hover:not(:disabled) {
1483
+ border-color: rgba(255, 255, 255, 0.3);
1484
+ }
1485
+
1486
+ .taskon-verify-btn:disabled {
1487
+ opacity: 0.5;
1488
+ cursor: not-allowed;
1489
+ }
1490
+
1491
+ .taskon-verify-btn--loading {
1492
+ pointer-events: none;
1493
+ }
1494
+
1495
+ .taskon-verify-btn-spinner {
1496
+ width: 16px;
1497
+ height: 16px;
1498
+ animation: taskon-spin 1s linear infinite;
1499
+ }
1500
+
1501
+ /* ============================================
1502
+ ExpandableContent Styles
1503
+ ============================================ */
1504
+ .taskon-expandable {
1505
+ display: flex;
1506
+ flex-direction: column;
1507
+ }
1508
+
1509
+ .taskon-expandable-content {
1510
+ position: relative;
1511
+ }
1512
+
1513
+ .taskon-expandable-toggle {
1514
+ display: inline-flex;
1515
+ align-items: center;
1516
+ gap: 4px;
1517
+ padding: 0;
1518
+ margin-top: 8px;
1519
+ font-size: 13px;
1520
+ font-weight: 500;
1521
+ color: #ffffff;
1522
+ background: transparent;
1523
+ border: none;
1524
+ cursor: pointer;
1525
+ transition: opacity var(--taskon-task-transition);
1526
+ align-self: flex-start;
1527
+ }
1528
+
1529
+ .taskon-expandable-toggle:hover {
1530
+ opacity: 0.8;
1531
+ }
1532
+
1533
+ .taskon-expandable-toggle-text {
1534
+ line-height: 1;
1535
+ }
1536
+
1537
+ .taskon-expandable-toggle-icon {
1538
+ transition: transform var(--taskon-task-transition);
1539
+ flex-shrink: 0;
1540
+ }
1541
+
1542
+ .taskon-expandable-toggle-icon--expanded {
1543
+ transform: rotate(180deg);
1544
+ }
1545
+
1546
+ /* ============================================
1547
+ Responsive Styles
1548
+ ============================================ */
1549
+ @media (max-width: 750px) {
1550
+ .taskon-task-item {
1551
+ padding: 4vw;
1552
+ }
1553
+
1554
+ .taskon-task-item-body {
1555
+ margin-left: 9.333vw;
1556
+ }
1557
+
1558
+ .taskon-task-item-icon {
1559
+ margin-right: 2.667vw;
1560
+ }
1561
+
1562
+ .taskon-task-item-right {
1563
+ margin-left: 2.67vw;
1564
+ }
1565
+
1566
+ .taskon-task-item-title {
1567
+ font-weight: 400;
1568
+ font-size: 3.733vw;
1569
+ line-height: 4.667vw;
1570
+ }
1571
+
1572
+ .taskon-task-item-desc {
1573
+ font-size: 3.2vw;
1574
+ line-height: 4vw;
1575
+ }
1576
+
1577
+ .taskon-task-icon-img {
1578
+ width: 6.667vw !important;
1579
+ height: 6.667vw !important;
1580
+ }
1581
+
1582
+ /* Points display mobile - 参考 TaskPoint.vue */
1583
+ .taskon-task-item-points {
1584
+ min-width: 6.8vw;
1585
+ height: 6.67vw;
1586
+ padding: 0 2vw;
1587
+ font-size: 2.93vw;
1588
+ border-radius: 0.91vw;
1589
+ }
1590
+
1591
+ .taskon-task-item-points-time {
1592
+ font-size: 1.85vw;
1593
+ }
1594
+ }
1595
+
1596
+ /* ============================================
1597
+ TimeRange Styles
1598
+ 与 Vue 版本 TimeRange.vue 样式一致
1599
+ ============================================ */
1600
+ .taskon-task-time-range {
1601
+ font-size: 14px;
1602
+ line-height: 18px;
1603
+ margin-top: 14px;
1604
+ }
1605
+
1606
+ .taskon-task-time-range-label {
1607
+ color: var(--taskon-task-text-secondary);
1608
+ }
1609
+
1610
+ .taskon-task-time-range-value {
1611
+ display: inline-block;
1612
+ color: rgba(255, 212, 101, 1);
1613
+ }
1614
+
1615
+ /* ============================================
1616
+ VerifyButton Cooldown Progress Bar
1617
+ 与 Vue 版本 VerifyButton.vue 冷却进度条样式一致
1618
+ ============================================ */
1619
+ .taskon-verify-btn-wrap {
1620
+ position: relative;
1621
+ display: inline-block;
1622
+ overflow: hidden;
1623
+ border-radius: 6px;
1624
+ }
1625
+
1626
+ .taskon-verify-btn-progress {
1627
+ position: absolute;
1628
+ bottom: 0;
1629
+ left: 0;
1630
+ right: 0;
1631
+ height: 3px;
1632
+ }
1633
+
1634
+ .taskon-verify-btn-progress-bar {
1635
+ height: 100%;
1636
+ border-radius: 6px;
1637
+ background: linear-gradient(to right, #cbff01, #00ffa3);
1638
+ }
1639
+ /**
1640
+ * BlindBox 盲盒组件样式
1641
+ * @module widgets/Quest/components/BlindBox/styles/blind-box.css
1642
+ *
1643
+ * Migrated from Vue version with Tailwind classes converted to CSS
1644
+ */
1645
+
1646
+ /* ============================================================================
1647
+ BlindBox Dialog - 开盲盒交互弹窗
1648
+ ============================================================================ */
1649
+
1650
+ .taskon-quest-blindbox-dialog {
1651
+ position: relative;
1652
+ width: min(520px, 92vw);
1653
+ overflow: hidden;
1654
+ padding-top: 40px;
1655
+ }
1656
+
1657
+ .taskon-quest-blindbox-dialog-title {
1658
+ margin: 0 0 16px;
1659
+ padding: 0 40px;
1660
+ font-size: 22px;
1661
+ font-weight: 600;
1662
+ line-height: 1.4;
1663
+ color: #fff;
1664
+ }
1665
+
1666
+ /* Stage container - centered square area for animation */
1667
+ .taskon-quest-blindbox-stage {
1668
+ position: relative;
1669
+ display: flex;
1670
+ align-items: center;
1671
+ justify-content: center;
1672
+ width: 100%;
1673
+ max-width: 420px;
1674
+ margin: 0 auto;
1675
+ aspect-ratio: 1;
1676
+ overflow: visible;
1677
+ border-radius: 32px;
1678
+ background: transparent;
1679
+ }
1680
+
1681
+ /* Background spinning light */
1682
+ .taskon-quest-blindbox-bg {
1683
+ position: absolute;
1684
+ left: 50%;
1685
+ top: calc(40% + 20px);
1686
+ width: min(80%, 340px);
1687
+ transform: translate(-50%, -50%);
1688
+ pointer-events: none;
1689
+ opacity: 0.75;
1690
+ animation: taskon-blindbox-spin 14s linear infinite;
1691
+ }
1692
+
1693
+ .taskon-quest-blindbox-bg img {
1694
+ width: 100%;
1695
+ height: auto;
1696
+ }
1697
+
1698
+ @keyframes taskon-blindbox-spin {
1699
+ from {
1700
+ transform: translate(-50%, -50%) rotate(0deg);
1701
+ }
1702
+ to {
1703
+ transform: translate(-50%, -50%) rotate(360deg);
1704
+ }
1705
+ }
1706
+
1707
+ /* Drop zone - collision detection area */
1708
+ .taskon-quest-blindbox-dropzone {
1709
+ position: absolute;
1710
+ left: 50%;
1711
+ top: calc(40% + 20px);
1712
+ width: min(33%, 145px);
1713
+ height: min(33%, 145px);
1714
+ transform: translate(-50%, -50%);
1715
+ pointer-events: none;
1716
+ }
1717
+
1718
+ /* Chest container */
1719
+ .taskon-quest-blindbox-chest {
1720
+ position: absolute;
1721
+ left: 50%;
1722
+ top: 40%;
1723
+ width: min(75%, 350px);
1724
+ height: auto;
1725
+ transform: translate(-50%, -50%);
1726
+ pointer-events: none;
1727
+ transition: filter 0.2s ease;
1728
+ }
1729
+
1730
+ .taskon-quest-blindbox-chest--highlighted {
1731
+ filter: drop-shadow(0 0 16px rgba(233, 168, 30, 0.55));
1732
+ }
1733
+
1734
+ .taskon-quest-blindbox-chest--open {
1735
+ filter: drop-shadow(0 0 22px rgba(255, 205, 112, 0.75));
1736
+ }
1737
+
1738
+ /* Ensure Lottie SVG fills container */
1739
+ .taskon-quest-blindbox-chest svg {
1740
+ width: 100% !important;
1741
+ height: auto !important;
1742
+ }
1743
+
1744
+ /* Key image */
1745
+ .taskon-quest-blindbox-key {
1746
+ position: absolute;
1747
+ width: clamp(80px, 16vw, 100px);
1748
+ transform: translate(-50%, -50%);
1749
+ cursor: grab;
1750
+ touch-action: none;
1751
+ user-select: none;
1752
+ transition: transform 0.2s ease, filter 0.2s ease;
1753
+ pointer-events: auto;
1754
+ }
1755
+
1756
+ .taskon-quest-blindbox-key--dragging {
1757
+ transform: translate(-50%, -50%) scale(1.04);
1758
+ cursor: grabbing;
1759
+ }
1760
+
1761
+ .taskon-quest-blindbox-key--hovering {
1762
+ filter: drop-shadow(0 0 18px rgba(255, 211, 103, 0.8));
1763
+ }
1764
+
1765
+ .taskon-quest-blindbox-key--disabled {
1766
+ pointer-events: none;
1767
+ opacity: 0.6;
1768
+ }
1769
+
1770
+ /* ============================================================================
1771
+ BlindBox Reward Dialog - 奖励结果展示弹窗
1772
+ ============================================================================ */
1773
+
1774
+ .taskon-quest-blindbox-reward {
1775
+ position: relative;
1776
+ width: 510px;
1777
+ max-width: 92vw;
1778
+ padding: 64px 40px;
1779
+ text-align: center;
1780
+ color: #fff;
1781
+ overflow: hidden;
1782
+ }
1783
+
1784
+ /* Light background effect */
1785
+ .taskon-quest-blindbox-reward-light {
1786
+ position: absolute;
1787
+ top: 0;
1788
+ left: 50%;
1789
+ width: 120%;
1790
+ max-width: none;
1791
+ transform: translateX(-50%);
1792
+ object-fit: contain;
1793
+ pointer-events: none;
1794
+ opacity: 0;
1795
+ animation: taskon-blindbox-light-appear 2s ease-out forwards;
1796
+ }
1797
+
1798
+ @keyframes taskon-blindbox-light-appear {
1799
+ to {
1800
+ opacity: 1;
1801
+ }
1802
+ }
1803
+
1804
+ /* Title */
1805
+ .taskon-quest-blindbox-reward-title {
1806
+ font-size: 32px;
1807
+ font-weight: 600;
1808
+ line-height: 40px;
1809
+ margin: 0;
1810
+ }
1811
+
1812
+ /* Subtitle */
1813
+ .taskon-quest-blindbox-reward-subtitle {
1814
+ margin-top: 12px;
1815
+ font-size: 16px;
1816
+ line-height: 1.5;
1817
+ color: rgba(255, 255, 255, 0.7);
1818
+ }
1819
+
1820
+ /* Rewards container - Green border and background like Vue version */
1821
+ .taskon-quest-blindbox-reward-list {
1822
+ display: inline-flex;
1823
+ flex-wrap: wrap;
1824
+ justify-content: center;
1825
+ align-items: center;
1826
+ margin-top: 24px;
1827
+ gap: 8px;
1828
+ padding: 12px 16px;
1829
+ border-radius: 8px;
1830
+ border: 1px solid rgba(60, 232, 155, 0.2);
1831
+ background: rgba(0, 255, 163, 0.1);
1832
+ }
1833
+
1834
+ /* Single reward card - transparent background */
1835
+ .taskon-quest-blindbox-reward-card {
1836
+ display: flex;
1837
+ flex-direction: column;
1838
+ align-items: center;
1839
+ justify-content: center;
1840
+ padding: 12px 16px;
1841
+ background: transparent;
1842
+ border-radius: 0;
1843
+ min-width: 60px;
1844
+ min-height: 80px;
1845
+ gap: 8px;
1846
+ }
1847
+
1848
+ .taskon-quest-blindbox-reward-card-icon {
1849
+ width: 32px;
1850
+ height: 32px;
1851
+ object-fit: contain;
1852
+ border-radius: 50%;
1853
+ }
1854
+
1855
+ /* Token amount with orange color and underline like Vue version */
1856
+ .taskon-quest-blindbox-reward-card-amount {
1857
+ font-size: 18px;
1858
+ font-weight: 600;
1859
+ color: #fbb15a;
1860
+ text-decoration: underline;
1861
+ }
1862
+
1863
+ .taskon-quest-blindbox-reward-card-name {
1864
+ font-size: 14px;
1865
+ color: #fbb15a;
1866
+ text-decoration: underline;
1867
+ }
1868
+
1869
+ .taskon-quest-blindbox-reward-card-value {
1870
+ font-size: 12px;
1871
+ color: rgba(255, 255, 255, 0.5);
1872
+ margin-top: 2px;
1873
+ }
1874
+
1875
+ /* Back button */
1876
+ .taskon-quest-blindbox-reward-btn-wrap {
1877
+ display: flex;
1878
+ justify-content: center;
1879
+ margin-top: 60px;
1880
+ }
1881
+
1882
+ /* Back button - matches Vue g-button--light-border */
1883
+ .taskon-quest-blindbox-reward-btn {
1884
+ height: 36px;
1885
+ padding: 0 24px;
1886
+ font-size: 14px;
1887
+ font-weight: 500;
1888
+ color: #fff;
1889
+ background: transparent;
1890
+ border: 1px solid #fff;
1891
+ border-radius: 8px;
1892
+ cursor: pointer;
1893
+ transition: opacity 0.2s ease;
1894
+ }
1895
+
1896
+ .taskon-quest-blindbox-reward-btn:hover {
1897
+ opacity: 0.8;
1898
+ }
1899
+
1900
+ .taskon-quest-blindbox-reward-btn:disabled {
1901
+ opacity: 0.5;
1902
+ cursor: not-allowed;
1903
+ }
1904
+
1905
+ /* ============================================================================
1906
+ OperateFooter - 开盲盒按钮
1907
+ ============================================================================ */
1908
+
1909
+ .taskon-quest-footer-blindbox-btn {
1910
+ display: flex;
1911
+ align-items: center;
1912
+ justify-content: center;
1913
+ gap: 8px;
1914
+ width: 100%;
1915
+ padding: 14px 24px;
1916
+ font-size: 16px;
1917
+ font-weight: 600;
1918
+ color: #000;
1919
+ background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
1920
+ border: none;
1921
+ border-radius: 12px;
1922
+ cursor: pointer;
1923
+ transition: all 0.2s ease;
1924
+ }
1925
+
1926
+ .taskon-quest-footer-blindbox-btn:hover {
1927
+ transform: translateY(-1px);
1928
+ box-shadow: 0 4px 16px rgba(255, 215, 0, 0.4);
1929
+ }
1930
+
1931
+ .taskon-quest-footer-blindbox-btn:active {
1932
+ transform: translateY(0);
1933
+ }
1934
+
1935
+ .taskon-quest-footer-blindbox-btn-icon {
1936
+ width: 24px;
1937
+ height: 24px;
1938
+ }
1939
+
1940
+ /* ============================================================================
1941
+ Mobile Responsive
1942
+ ============================================================================ */
1943
+
1944
+ @media (max-width: 768px) {
1945
+ .taskon-quest-blindbox-dialog {
1946
+ padding-top: 24px;
1947
+ }
1948
+
1949
+ .taskon-quest-blindbox-dialog-title {
1950
+ padding: 0 24px;
1951
+ font-size: 18px;
1952
+ }
1953
+
1954
+ .taskon-quest-blindbox-reward {
1955
+ padding: 48px 24px;
1956
+ }
1957
+
1958
+ .taskon-quest-blindbox-reward-title {
1959
+ font-size: 24px;
1960
+ line-height: 32px;
1961
+ }
1962
+
1963
+ .taskon-quest-blindbox-reward-btn-wrap {
1964
+ margin-top: 40px;
1965
+ }
1966
+ }