Constrain funds bar width and fold strategy rules.
Match page max-width on ultrawide and move the plan subtitle into a collapsible rules section under the funds strip. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -163,6 +163,9 @@ async def funds_summary(_user: Annotated[str, Depends(require_user)]) -> dict[st
|
|||||||
"options_trading_label": _fmt_opt(opt_t_usdc, opt_t_usdt),
|
"options_trading_label": _fmt_opt(opt_t_usdc, opt_t_usdt),
|
||||||
"realtime_pnl": realtime,
|
"realtime_pnl": realtime,
|
||||||
"usdc_usdt_rate": rate,
|
"usdc_usdt_rate": rate,
|
||||||
|
"perp_inst_id": str(
|
||||||
|
db.get_setting("perp_inst_id") or s.perp_inst_id or "ETH-USDT-SWAP"
|
||||||
|
),
|
||||||
"updated_at_ms": int(datetime.now(timezone.utc).timestamp() * 1000),
|
"updated_at_ms": int(datetime.now(timezone.utc).timestamp() * 1000),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-07-29 — 资金条与内容区同宽;规则说明折叠
|
||||||
|
|
||||||
|
### 变更
|
||||||
|
|
||||||
|
1. 资金横条内容区与下方页面同宽(带鱼屏不再拉满全屏)。
|
||||||
|
2. 原计划页说明文案收入资金条下方「规则说明」折叠。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2026-07-29 — 资金条 + USDT/USDC 兑换划转(SIM/LIVE)
|
## 2026-07-29 — 资金条 + USDT/USDC 兑换划转(SIM/LIVE)
|
||||||
|
|
||||||
### 变更
|
### 变更
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export type FundsSummary = {
|
|||||||
options_trading_label: string;
|
options_trading_label: string;
|
||||||
realtime_pnl: number | null;
|
realtime_pnl: number | null;
|
||||||
usdc_usdt_rate?: number;
|
usdc_usdt_rate?: number;
|
||||||
|
perp_inst_id?: string;
|
||||||
detail?: string;
|
detail?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ function pnlClass(n: number | null | undefined) {
|
|||||||
|
|
||||||
export default function FundsBar() {
|
export default function FundsBar() {
|
||||||
const [s, setS] = useState<FundsSummary | null>(null);
|
const [s, setS] = useState<FundsSummary | null>(null);
|
||||||
|
const [rulesOpen, setRulesOpen] = useState(false);
|
||||||
|
|
||||||
const load = useCallback(() => {
|
const load = useCallback(() => {
|
||||||
apiFetch<FundsSummary>("/api/funds/summary")
|
apiFetch<FundsSummary>("/api/funds/summary")
|
||||||
@@ -47,56 +49,83 @@ export default function FundsBar() {
|
|||||||
|
|
||||||
if (!s?.ok) return null;
|
if (!s?.ok) return null;
|
||||||
|
|
||||||
|
const rulesText = `行情 ${s.exchange || "OKX"} · ${
|
||||||
|
s.perp_inst_id || "ETH-USDT-SWAP"
|
||||||
|
} · 目标平仓(双腿/远虚只平永续) · 未达标则到期结算`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="funds-bar" aria-label="资金与统计">
|
<div className="funds-bar-shell">
|
||||||
<div className="funds-item funds-item--primary">
|
<div className="funds-bar-inner">
|
||||||
<div className="funds-label">交易所</div>
|
<div className="funds-bar" aria-label="资金与统计">
|
||||||
<div className="funds-value">{s.exchange || "—"}</div>
|
<div className="funds-item funds-item--primary">
|
||||||
</div>
|
<div className="funds-label">交易所</div>
|
||||||
<div className="funds-item">
|
<div className="funds-value">{s.exchange || "—"}</div>
|
||||||
<div className="funds-label">交易日</div>
|
</div>
|
||||||
<div className="funds-value mono">{s.trading_day}</div>
|
<div className="funds-item">
|
||||||
</div>
|
<div className="funds-label">交易日</div>
|
||||||
<div className="funds-item funds-item--primary">
|
<div className="funds-value mono">{s.trading_day}</div>
|
||||||
<div className="funds-label">总交易</div>
|
</div>
|
||||||
<div className="funds-value mono">{s.total_trades}</div>
|
<div className="funds-item funds-item--primary">
|
||||||
</div>
|
<div className="funds-label">总交易</div>
|
||||||
<div className="funds-item">
|
<div className="funds-value mono">{s.total_trades}</div>
|
||||||
<div className="funds-label">胜率</div>
|
</div>
|
||||||
<div className="funds-value mono">
|
<div className="funds-item">
|
||||||
{(s.win_rate * 100).toFixed(0)}%
|
<div className="funds-label">胜率</div>
|
||||||
|
<div className="funds-value mono">
|
||||||
|
{(s.win_rate * 100).toFixed(0)}%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="funds-item" title="平均盈利 ÷ 平均亏损">
|
||||||
|
<div className="funds-label">盈亏比</div>
|
||||||
|
<div className="funds-value mono">
|
||||||
|
{s.profit_loss_ratio != null
|
||||||
|
? s.profit_loss_ratio.toFixed(2)
|
||||||
|
: "—"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="funds-item">
|
||||||
|
<div className="funds-label">总资金</div>
|
||||||
|
<div className="funds-value mono">{fmtU(s.total_funds)}</div>
|
||||||
|
</div>
|
||||||
|
<div className="funds-item">
|
||||||
|
<div className="funds-label">资金账户</div>
|
||||||
|
<div className="funds-value mono">{fmtU(s.funding_usdt)}</div>
|
||||||
|
</div>
|
||||||
|
<div className="funds-item">
|
||||||
|
<div className="funds-label">交易账户</div>
|
||||||
|
<div className="funds-value mono">{fmtU(s.trading_usdt)}</div>
|
||||||
|
</div>
|
||||||
|
<div className="funds-item">
|
||||||
|
<div className="funds-label">期权资金账户</div>
|
||||||
|
<div className="funds-value mono">{s.options_funding_label}</div>
|
||||||
|
</div>
|
||||||
|
<div className="funds-item">
|
||||||
|
<div className="funds-label">期权交易账户</div>
|
||||||
|
<div className="funds-value mono">{s.options_trading_label}</div>
|
||||||
|
</div>
|
||||||
|
<div className="funds-item funds-item--pnl">
|
||||||
|
<div className="funds-label">实时盈亏</div>
|
||||||
|
<div className={`funds-value mono ${pnlClass(s.realtime_pnl)}`}>
|
||||||
|
{s.realtime_pnl == null ? "—" : fmtU(s.realtime_pnl)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div className="funds-item" title="平均盈利 ÷ 平均亏损">
|
<div className="funds-rules">
|
||||||
<div className="funds-label">盈亏比</div>
|
<button
|
||||||
<div className="funds-value mono">
|
type="button"
|
||||||
{s.profit_loss_ratio != null ? s.profit_loss_ratio.toFixed(2) : "—"}
|
className="funds-rules-toggle"
|
||||||
</div>
|
aria-expanded={rulesOpen}
|
||||||
</div>
|
onClick={() => setRulesOpen((v) => !v)}
|
||||||
<div className="funds-item">
|
>
|
||||||
<div className="funds-label">总资金</div>
|
<span>规则说明</span>
|
||||||
<div className="funds-value mono">{fmtU(s.total_funds)}</div>
|
<span className="funds-rules-chevron" aria-hidden>
|
||||||
</div>
|
{rulesOpen ? "▾" : "▸"}
|
||||||
<div className="funds-item">
|
</span>
|
||||||
<div className="funds-label">资金账户</div>
|
</button>
|
||||||
<div className="funds-value mono">{fmtU(s.funding_usdt)}</div>
|
{rulesOpen ? (
|
||||||
</div>
|
<p className="funds-rules-body meta">{rulesText}</p>
|
||||||
<div className="funds-item">
|
) : null}
|
||||||
<div className="funds-label">交易账户</div>
|
|
||||||
<div className="funds-value mono">{fmtU(s.trading_usdt)}</div>
|
|
||||||
</div>
|
|
||||||
<div className="funds-item">
|
|
||||||
<div className="funds-label">期权资金账户</div>
|
|
||||||
<div className="funds-value mono">{s.options_funding_label}</div>
|
|
||||||
</div>
|
|
||||||
<div className="funds-item">
|
|
||||||
<div className="funds-label">期权交易账户</div>
|
|
||||||
<div className="funds-value mono">{s.options_trading_label}</div>
|
|
||||||
</div>
|
|
||||||
<div className="funds-item funds-item--pnl">
|
|
||||||
<div className="funds-label">实时盈亏</div>
|
|
||||||
<div className={`funds-value mono ${pnlClass(s.realtime_pnl)}`}>
|
|
||||||
{s.realtime_pnl == null ? "—" : fmtU(s.realtime_pnl)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -167,14 +167,6 @@ export default function PlanPage() {
|
|||||||
<div className="plan-page">
|
<div className="plan-page">
|
||||||
<div className="plan-desktop-head">
|
<div className="plan-desktop-head">
|
||||||
<h2 style={{ marginTop: 0 }}>自动对冲计划</h2>
|
<h2 style={{ marginTop: 0 }}>自动对冲计划</h2>
|
||||||
<p style={{ color: "var(--muted)", marginTop: -8 }}>
|
|
||||||
行情 {(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>
|
</div>
|
||||||
|
|
||||||
{/* 手机端一屏监控卡:状态 / 净利 / 倒计时 */}
|
{/* 手机端一屏监控卡:状态 / 净利 / 倒计时 */}
|
||||||
|
|||||||
@@ -83,13 +83,32 @@ input {
|
|||||||
grid-template-rows: auto auto 1fr;
|
grid-template-rows: auto auto 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.funds-bar-shell {
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
background: rgba(18, 22, 28, 0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.funds-bar-inner {
|
||||||
|
width: 100%;
|
||||||
|
max-width: min(1680px, 100%);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1800px) {
|
||||||
|
.funds-bar-inner {
|
||||||
|
max-width: 1760px;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.funds-bar {
|
.funds-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 2px 0;
|
gap: 2px 0;
|
||||||
padding: 8px 12px;
|
padding: 8px 0 4px;
|
||||||
border-bottom: 1px solid var(--line);
|
|
||||||
background: rgba(18, 22, 28, 0.96);
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
@@ -128,6 +147,40 @@ input {
|
|||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.funds-rules {
|
||||||
|
padding: 2px 10px 8px;
|
||||||
|
border-top: 1px solid rgba(30, 38, 48, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.funds-rules-toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.funds-rules-toggle:hover {
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.funds-rules-chevron {
|
||||||
|
font-size: 11px;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.funds-rules-body {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.45;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
.topnav {
|
.topnav {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto 1fr;
|
grid-template-columns: 1fr auto 1fr;
|
||||||
|
|||||||
Reference in New Issue
Block a user