feat: Implement initial backend API server with various endpoints and background services, including an error account cleaner.

This commit is contained in:
2026-02-05 07:51:03 +08:00
parent ad1270b88d
commit db00d44a71
4 changed files with 22 additions and 14 deletions

View File

@@ -508,7 +508,7 @@ func handleS2ATest(w http.ResponseWriter, r *http.Request) {
}
// 请求 S2A 仪表盘接口
dashboardURL := config.Global.S2AApiBase + "/api/v1/admin/dashboard"
dashboardURL := config.Global.S2AApiBase + "/api/v1/admin/dashboard/stats"
req, err := http.NewRequest("GET", dashboardURL, nil)
if err != nil {
api.Error(w, http.StatusInternalServerError, "创建请求失败")

View File

@@ -75,7 +75,7 @@ func getTotalAccountCount() (int, error) {
}
client := &http.Client{Timeout: 30 * time.Second}
url := fmt.Sprintf("%s/api/v1/admin/dashboard", config.Global.S2AApiBase)
url := fmt.Sprintf("%s/api/v1/admin/dashboard/stats", config.Global.S2AApiBase)
req, err := http.NewRequest("GET", url, nil)
if err != nil {

View File

@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react'
import { Users, CheckCircle, XCircle, AlertTriangle, Zap, Activity, TrendingUp } from 'lucide-react'
import { Users, CheckCircle, XCircle, AlertTriangle, Zap, Activity } from 'lucide-react'
import type { DashboardStats } from '../../types'
import StatsCard from './StatsCard'
@@ -78,17 +78,15 @@ export default function PoolStatus({ stats, loading, error }: PoolStatusProps) {
color="slate"
loading={loading}
/>
{/* RPM 卡片 - 显示当前 RPM 和今日最高 */}
<div className="relative">
<StatsCard title="RPM" value={stats?.rpm ?? 0} icon={Zap} color="blue" loading={loading} />
{/* 今日最高 RPM 显示在卡片下方 */}
{maxRpm > 0 && (
<div className="absolute -bottom-5 left-0 right-0 flex items-center justify-center gap-1 text-xs text-slate-500 dark:text-slate-400">
<TrendingUp className="h-3 w-3 text-orange-500" />
<span>: <span className="font-semibold text-orange-500">{maxRpm}</span></span>
</div>
)}
</div>
<StatsCard
title="RPM"
value={stats?.rpm ?? 0}
icon={Zap}
color="blue"
loading={loading}
subtitle={maxRpm > 0 ? `📈 今日最高: ${maxRpm}` : undefined}
/>
</div>
)
}

View File

@@ -10,6 +10,8 @@ interface StatsCardProps {
trendValue?: string
color?: 'blue' | 'green' | 'yellow' | 'red' | 'slate'
loading?: boolean
subtitle?: string
subtitleColor?: string
}
export default function StatsCard({
@@ -20,6 +22,8 @@ export default function StatsCard({
trendValue,
color = 'blue',
loading = false,
subtitle,
subtitleColor = 'text-orange-500',
}: StatsCardProps) {
const colorStyles = {
blue: {
@@ -80,6 +84,11 @@ export default function StatsCard({
</span>
</div>
)}
{subtitle && (
<p className={`mt-1 text-xs font-medium ${subtitleColor}`}>
{subtitle}
</p>
)}
{trend && trendValue && TrendIcon && (
<div className={`mt-2 flex items-center gap-1 text-sm ${trendStyles[trend].color}`}>
<TrendIcon className="h-4 w-4" />
@@ -94,3 +103,4 @@ export default function StatsCard({
</Card>
)
}