"use client"; import { useParams, useSearchParams, useRouter } from "next/navigation"; import { useEffect, useState, useCallback } from "react"; import { authFetch } from "@/lib/auth"; import Link from "next/link"; import dynamic from "next/dynamic"; import { ArrowLeft, CheckCircle, PauseCircle, AlertCircle, Clock, } from "lucide-react"; // ─── Dynamic imports for each strategy's pages ─────────────────── const SignalsV53 = dynamic(() => import("@/app/signals-v53/page"), { ssr: false }); const SignalsV53Fast = dynamic(() => import("@/app/signals-v53fast/page"), { ssr: false }); const SignalsV53Middle = dynamic(() => import("@/app/signals-v53middle/page"), { ssr: false }); const PaperV53 = dynamic(() => import("@/app/paper-v53/page"), { ssr: false }); const PaperV53Fast = dynamic(() => import("@/app/paper-v53fast/page"), { ssr: false }); const PaperV53Middle = dynamic(() => import("@/app/paper-v53middle/page"), { ssr: false }); // ─── Types ──────────────────────────────────────────────────────── interface StrategySummary { id: string; display_name: string; status: string; started_at: number; initial_balance: number; current_balance: number; net_usdt: number; net_r: number; trade_count: number; win_rate: number; avg_win_r: number; avg_loss_r: number; open_positions: number; pnl_usdt_24h: number; pnl_r_24h: number; cvd_windows?: string; description?: string; } // ─── Helpers ────────────────────────────────────────────────────── function fmtDur(ms: number) { const s = Math.floor((Date.now() - ms) / 1000); const d = Math.floor(s / 86400); const h = Math.floor((s % 86400) / 3600); const m = Math.floor((s % 3600) / 60); if (d > 0) return `${d}天${h}h`; if (h > 0) return `${h}h${m}m`; return `${m}m`; } function StatusBadge({ status }: { status: string }) { if (status === "running") return 运行中; if (status === "paused") return 已暂停; return 异常; } // ─── Content router ─────────────────────────────────────────────── function SignalsContent({ strategyId }: { strategyId: string }) { if (strategyId === "v53") return ; if (strategyId === "v53_fast") return ; if (strategyId === "v53_middle") return ; return
未知策略: {strategyId}
; } function PaperContent({ strategyId }: { strategyId: string }) { if (strategyId === "v53") return ; if (strategyId === "v53_fast") return ; if (strategyId === "v53_middle") return ; return
未知策略: {strategyId}
; } // ─── Main Page ──────────────────────────────────────────────────── export default function StrategyDetailPage() { const params = useParams(); const searchParams = useSearchParams(); const router = useRouter(); const strategyId = params?.id as string; const tab = searchParams?.get("tab") || "signals"; const [summary, setSummary] = useState(null); const [loading, setLoading] = useState(true); const fetchSummary = useCallback(async () => { try { const r = await authFetch(`/api/strategy-plaza/${strategyId}/summary`); if (r.ok) { const d = await r.json(); setSummary(d); } } catch {} setLoading(false); }, [strategyId]); useEffect(() => { fetchSummary(); const iv = setInterval(fetchSummary, 30000); return () => clearInterval(iv); }, [fetchSummary]); if (loading) { return (
加载中...
); } const isProfit = (summary?.net_usdt ?? 0) >= 0; return (
{/* Back + Strategy Header */}
策略广场 / {summary?.display_name ?? strategyId}
{/* Summary Bar */} {summary && (
运行 {fmtDur(summary.started_at)} {summary.cvd_windows && ( CVD {summary.cvd_windows} )} 胜率 = 50 ? "text-emerald-400 font-bold" : "text-yellow-400 font-bold"}>{summary.win_rate}% 净R {summary.net_r >= 0 ? "+" : ""}{summary.net_r}R 余额 {summary.current_balance.toLocaleString()} U 24h = 0 ? "text-emerald-400" : "text-red-400"}`}>{summary.pnl_usdt_24h >= 0 ? "+" : ""}{summary.pnl_usdt_24h} U
)} {/* Tabs */}
{[ { key: "signals", label: "📊 信号引擎" }, { key: "paper", label: "📈 模拟盘" }, ].map(({ key, label }) => ( ))}
{/* Content — direct render of existing pages */}
{tab === "signals" ? ( ) : ( )}
); }