Add mobile monitor layout with bottom nav and glance card.

EOF

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-27 06:54:42 +08:00
parent 56a4007130
commit 60112bf8eb
4 changed files with 343 additions and 43 deletions
+62 -12
View File
@@ -128,21 +128,71 @@ export default function PlanPage() {
const countdownUrgent =
open && expiryMs != null && expiryMs - nowMs > 0 && expiryMs - nowMs < 6 * 3600_000;
const venueShort =
plan?.mode === "LIVE"
? `实盘·${(snap?.exchange || "okx").toUpperCase()}`
: "模拟盘";
return (
<div>
<h2 style={{ marginTop: 0 }}></h2>
<p style={{ color: "var(--muted)", marginTop: -8 }}>
{plan?.mode === "LIVE" ? "LIVE 实盘下单" : "SIM 本地撮合"} · {" "}
{(snap?.exchange || "okx").toUpperCase()}
{snap?.perp_inst_id ? ` · ${snap.perp_inst_id}` : ""} ·
(/) ·
{plan?.mode === "LIVE" && plan.live_ready === false
? ` · 未就绪: ${plan.live_ready_reason || "请配置 API"}`
: ""}
</p>
<div className="plan-page">
<div className="plan-desktop-head">
<h2 style={{ marginTop: 0 }}></h2>
<p style={{ color: "var(--muted)", marginTop: -8 }}>
{plan?.mode === "LIVE" ? "LIVE 实盘下单" : "SIM 本地撮合"} · {" "}
{(snap?.exchange || "okx").toUpperCase()}
{snap?.perp_inst_id ? ` · ${snap.perp_inst_id}` : ""} ·
(/) ·
{plan?.mode === "LIVE" && plan.live_ready === false
? ` · 未就绪: ${plan.live_ready_reason || "请配置 API"}`
: ""}
</p>
</div>
{/* 手机端一屏监控卡:状态 / 净利 / 倒计时 */}
<section className="plan-mobile-hero" aria-label="监控摘要">
<div className="plan-mobile-hero-top">
<span
className={
plan?.running
? "plan-pill plan-pill-on"
: plan?.phase === "paused"
? "plan-pill plan-pill-pause"
: "plan-pill plan-pill-off"
}
>
{plan?.running ? "启动中" : plan?.phase === "paused" ? "已暂停" : "已停"}
</span>
<span className="plan-pill plan-pill-muted mono">{venueShort}</span>
<span className="plan-mobile-phase mono">{phaseLabel}</span>
</div>
<div className="plan-mobile-hero-pnl">
<div className="plan-mobile-pnl-block">
<span className="plan-mobile-label"></span>
<span className={`plan-mobile-pnl-num mono ${pnlClass(open ? netPnl : null)}`}>
{open ? fmt(netPnl) : "—"}
</span>
<span className="plan-mobile-sub mono"> {fmt(exitTarget)} U</span>
</div>
<div className="plan-mobile-pnl-block">
<span className="plan-mobile-label"></span>
<span
className={`plan-mobile-countdown mono ${countdownUrgent ? "pos-countdown-urgent" : ""}`}
>
{countdown}
</span>
<span className="plan-mobile-sub mono">
{open ? pos?.group_id || "持仓中" : "空仓"}
</span>
</div>
</div>
{plan?.last_error ? (
<div className="plan-mobile-err">{plan.last_error}</div>
) : null}
</section>
{err ? <div className="err">{err}</div> : null}
<div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 12 }}>
<div className="plan-actions">
<button
className={plan?.running ? "btn btn-running" : "btn"}
type="button"