Skip to content

Commit fbf203c

Browse files
committed
feat(frontend): improve dashboard UI and add plan tier badges
- Fix rate-limit card 5h/7d spacing by removing min-width constraint - Align model ranking chart leftward by reducing Y-axis width - Add colored plan badges (Pro/ProLite/Plus/Team/Free) with tier-based color depth - Remove local rate-limit pre-check from connection test flow - Add translator response normalization support
1 parent d9b4a8c commit fbf203c

6 files changed

Lines changed: 471 additions & 268 deletions

File tree

admin/test_connection.go

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,6 @@ func (h *Handler) TestConnection(c *gin.Context) {
7474
// 发送 test_start
7575
sendTestEvent(c, testEvent{Type: "test_start", Model: testModel})
7676

77-
if resetAt, ok := activeLocalRateLimitReset(account); ok && !forceConnectionTest(c) {
78-
sendTestEvent(c, testEvent{Type: "error", Error: formatLocalRateLimitTestError(resetAt)})
79-
return
80-
}
81-
8277
// 构建最小测试请求体(参考 sub2api createOpenAITestPayload)
8378
payload := buildTestPayload(testModel)
8479

@@ -229,44 +224,6 @@ func buildTestPayload(model string) []byte {
229224
return payload
230225
}
231226

232-
func forceConnectionTest(c *gin.Context) bool {
233-
if c == nil {
234-
return false
235-
}
236-
switch strings.ToLower(strings.TrimSpace(c.Query("force"))) {
237-
case "1", "true", "yes":
238-
return true
239-
default:
240-
return false
241-
}
242-
}
243-
244-
func activeLocalRateLimitReset(account *auth.Account) (time.Time, bool) {
245-
if account == nil {
246-
return time.Time{}, false
247-
}
248-
now := time.Now()
249-
if account.IsPremium5hRateLimited() {
250-
_, resetAt, ok := account.GetUsageSnapshot5h()
251-
if ok && resetAt.After(now) {
252-
return resetAt, true
253-
}
254-
}
255-
reason, until := account.GetCooldownSnapshot()
256-
if reason == "rate_limited" && until.After(now) {
257-
return until, true
258-
}
259-
return time.Time{}, false
260-
}
261-
262-
func formatLocalRateLimitTestError(resetAt time.Time) string {
263-
remaining := time.Until(resetAt).Round(time.Second)
264-
if remaining < 0 {
265-
remaining = 0
266-
}
267-
return fmt.Sprintf("账号当前处于本地限流状态,预计 %s 后恢复;本次未发送上游探针。需要强制探针时可添加 force=1。", remaining)
268-
}
269-
270227
func formatUsageLimitedTestError(state proxy.CodexUsageSyncResult) (string, bool) {
271228
if state.Premium5hRateLimited {
272229
remaining := time.Until(state.Reset5hAt).Round(time.Second)
@@ -523,11 +480,6 @@ func (h *Handler) BatchTest(c *gin.Context) {
523480
sem <- struct{}{}
524481
defer func() { <-sem }()
525482

526-
if _, ok := activeLocalRateLimitReset(acc); ok {
527-
atomic.AddInt64(&rateLimitCount, 1)
528-
return
529-
}
530-
531483
resp, err := proxy.ExecuteRequest(context.Background(), acc, payload, "", h.store.ResolveProxyForAccount(acc), "", nil, nil)
532484
if err != nil {
533485
h.store.MarkError(acc, "批量测试请求失败: "+err.Error())

admin/test_connection_test.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"testing"
66
"time"
77

8-
"github.com/codex2api/auth"
98
"github.com/codex2api/proxy"
109
"github.com/tidwall/gjson"
1110
)
@@ -32,24 +31,6 @@ func TestBuildTestPayloadUsesSelectedModel(t *testing.T) {
3231
}
3332
}
3433

35-
func TestActiveLocalRateLimitResetDetectsPremium5h(t *testing.T) {
36-
resetAt := time.Now().Add(30 * time.Minute)
37-
acc := &auth.Account{
38-
PlanType: "plus",
39-
UsagePercent5h: 100,
40-
UsagePercent5hValid: true,
41-
Reset5hAt: resetAt,
42-
}
43-
44-
got, ok := activeLocalRateLimitReset(acc)
45-
if !ok {
46-
t.Fatal("activeLocalRateLimitReset() ok = false, want true")
47-
}
48-
if !got.Equal(resetAt) {
49-
t.Fatalf("resetAt = %v, want %v", got, resetAt)
50-
}
51-
}
52-
5334
func TestFormatUsageLimitedTestErrorReportsSuccessfulProbeAsLimited(t *testing.T) {
5435
msg, limited := formatUsageLimitedTestError(proxy.CodexUsageSyncResult{
5536
Premium5hRateLimited: true,

frontend/src/components/DashboardUsageCharts.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,10 @@ export default function DashboardUsageCharts({
301301

302302
<ChartCard title={t('dashboard.modelRanking')} description={t('dashboard.modelRankingDesc')}>
303303
<ResponsiveContainer width="100%" height="100%">
304-
<BarChart data={displayData.modelData} layout="vertical" margin={{ top: 8, right: 12, left: 8, bottom: 0 }}>
304+
<BarChart data={displayData.modelData} layout="vertical" margin={{ top: 8, right: 12, left: 0, bottom: 0 }}>
305305
<CartesianGrid horizontal={false} stroke={gridColor} strokeDasharray="4 4" />
306306
<XAxis type="number" tickFormatter={formatCompactNumber} tick={{ fill: axisColor, fontSize: 12 }} axisLine={{ stroke: gridColor }} tickLine={{ stroke: gridColor }} allowDecimals={false} />
307-
<YAxis dataKey="shortModel" type="category" width={128} tick={{ fill: axisColor, fontSize: 12 }} axisLine={{ stroke: gridColor }} tickLine={{ stroke: gridColor }} />
307+
<YAxis dataKey="shortModel" type="category" width={80} tick={{ fill: axisColor, fontSize: 12 }} axisLine={{ stroke: gridColor }} tickLine={{ stroke: gridColor }} />
308308
<Tooltip
309309
position={{ y: 10 }}
310310
formatter={(value) => formatNumber(value)}

0 commit comments

Comments
 (0)