forked from shuyu-labs/WebCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgressTracker.razor
More file actions
119 lines (110 loc) · 5.12 KB
/
ProgressTracker.razor
File metadata and controls
119 lines (110 loc) · 5.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
@namespace WebCodeCli.Components
@if (_isVisible)
{
<div class="progress-tracker bg-white border border-gray-200 rounded-lg shadow-sm p-3 mb-3 animate-fadeIn">
<!-- 阶段指示器 -->
<div class="flex items-center justify-between mb-3 overflow-x-auto pb-1">
@foreach (var stage in _stages)
{
<div class="flex flex-col items-center gap-1 flex-shrink-0">
<div class="@GetStageClass(stage) flex items-center justify-center w-8 h-8 sm:w-10 sm:h-10 rounded-full transition-all duration-300">
@if (stage.Status == StageStatus.Completed)
{
<svg class="w-4 h-4 sm:w-5 sm:h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path>
</svg>
}
else if (stage.Status == StageStatus.Active)
{
<div class="animate-spin rounded-full h-4 w-4 sm:h-5 sm:w-5 border-2 border-white border-t-transparent"></div>
}
else if (stage.Status == StageStatus.Failed)
{
<svg class="w-4 h-4 sm:w-5 sm:h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M6 18L18 6M6 6l12 12"></path>
</svg>
}
else
{
<span class="text-xs sm:text-sm text-gray-500">@stage.Icon</span>
}
</div>
<!-- 阶段名称 -->
<span class="@GetStageNameClass(stage) text-[10px] sm:text-xs font-medium whitespace-nowrap">
@stage.Name
</span>
</div>
@if (stage != _stages.Last())
{
<div class="@GetConnectorClass(stage) h-0.5 w-8 sm:w-12 mx-1 transition-all duration-500 self-start mt-4 sm:mt-5"></div>
}
}
</div>
<!-- 进度条 -->
<div class="relative w-full h-1.5 bg-gray-100 rounded-full overflow-hidden mb-2">
<div class="@GetProgressBarClass() h-full rounded-full transition-all duration-500 ease-out relative overflow-hidden"
style="width: @(_progress)%">
<div class="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent animate-shimmer"></div>
</div>
</div>
<!-- 信息栏 -->
<div class="flex items-center justify-between text-xs sm:text-sm">
<div class="flex items-center gap-2">
<span class="font-medium text-gray-600">@T("common.currentStage"):</span>
<span class="@GetCurrentStageTextClass() font-semibold">@_currentStageText</span>
</div>
<div class="flex items-center gap-3">
<div class="flex items-center gap-1 text-gray-500">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span class="font-mono text-gray-600">@_elapsedTime</span>
</div>
@if (_canCancel && !_isCompleted && !_isFailed)
{
<button @onclick="OnCancelClick"
class="btn-default text-xs py-0.5 px-2 flex items-center gap-1 hover:bg-red-50 hover:text-red-600 hover:border-red-300"
title="@T("common.cancel")">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
<span>@T("common.cancel")</span>
</button>
}
</div>
</div>
<!-- 详细信息(可选) -->
@if (!string.IsNullOrEmpty(_detailMessage))
{
<div class="mt-2 pt-2 border-t border-gray-100">
<p class="text-[10px] sm:text-xs text-gray-500">@_detailMessage</p>
</div>
}
</div>
}
<style>
@@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.animate-fadeIn {
animation: fadeIn 0.3s ease-out;
}
.animate-shimmer {
animation: shimmer 2s infinite;
}
</style>