UI: centered nav title, settings tabs, running status, manual buttons.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,7 +27,7 @@ export default function LoginPage() {
|
||||
return (
|
||||
<div className="login-wrap">
|
||||
<form className="login-box" onSubmit={onSubmit}>
|
||||
<h1>eth_hedge_sim</h1>
|
||||
<h1>OKX 自动化对冲系统</h1>
|
||||
<p>模拟盘登录</p>
|
||||
{err ? <div className="err">{err}</div> : null}
|
||||
<div className="field">
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function PlanPage() {
|
||||
disabled={!!busy}
|
||||
onClick={() => act("/api/sim/open-group", "open")}
|
||||
>
|
||||
模拟开一组
|
||||
手动开一组
|
||||
</button>
|
||||
<button
|
||||
className="btn ghost"
|
||||
@@ -98,7 +98,7 @@ export default function PlanPage() {
|
||||
disabled={!!busy}
|
||||
onClick={() => act("/api/sim/close-group", "close")}
|
||||
>
|
||||
模拟全平
|
||||
手动全平
|
||||
</button>
|
||||
<button
|
||||
className="btn ghost"
|
||||
@@ -115,8 +115,12 @@ export default function PlanPage() {
|
||||
<div className="kv">
|
||||
<span>策略</span>
|
||||
<span className="mono">
|
||||
{plan?.running ? "运行中" : "已停"} · {plan?.phase || "—"} · 轮次{" "}
|
||||
{plan?.rounds_done ?? 0}/{plan?.max_rounds ?? 3}
|
||||
{plan?.running ? (
|
||||
<span className="status-running">启动中</span>
|
||||
) : (
|
||||
<span className="status-stopped">已停</span>
|
||||
)}{" "}
|
||||
· {plan?.phase || "—"} · 轮次 {plan?.rounds_done ?? 0}/{plan?.max_rounds ?? 3}
|
||||
</span>
|
||||
</div>
|
||||
<div className="kv">
|
||||
|
||||
+128
-105
@@ -7,7 +7,11 @@ import {
|
||||
StrategySettings,
|
||||
} from "../api/client";
|
||||
|
||||
type Tab = "strategy" | "account";
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [tab, setTab] = useState<Tab>("strategy");
|
||||
|
||||
const [newUsername, setNewUsername] = useState(getUsername() || "admin");
|
||||
const [currentPassword, setCurrentPassword] = useState("");
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
@@ -85,113 +89,132 @@ export default function SettingsPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: "grid", gap: 16, maxWidth: 560 }}>
|
||||
<div className="card">
|
||||
<h2 style={{ marginTop: 0 }}>策略设置</h2>
|
||||
<p style={{ color: "var(--muted)" }}>
|
||||
标的波动 N 点全平、轮次休息、费率(滑点=1×费率)。
|
||||
</p>
|
||||
{stratOk ? <div style={{ color: "var(--up)", marginBottom: 12 }}>{stratOk}</div> : null}
|
||||
<form onSubmit={onSaveStrategy}>
|
||||
<div className="field">
|
||||
<label htmlFor="exit">EXIT_MOVE_POINTS(标的波动点数)</label>
|
||||
<input
|
||||
id="exit"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={exitPts}
|
||||
onChange={(e) => setExitPts(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="rest">REST_SECONDS(轮间休息秒)</label>
|
||||
<input
|
||||
id="rest"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={rest}
|
||||
onChange={(e) => setRest(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="rounds">MAX_ROUNDS</label>
|
||||
<input
|
||||
id="rounds"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={maxRounds}
|
||||
onChange={(e) => setMaxRounds(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="fee">FEE_RATE</label>
|
||||
<input
|
||||
id="fee"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.0001"
|
||||
value={fee}
|
||||
onChange={(e) => setFee(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<button className="btn" type="submit">
|
||||
保存策略
|
||||
</button>
|
||||
</form>
|
||||
<div style={{ maxWidth: 560 }}>
|
||||
<h2 style={{ marginTop: 0 }}>系统设置</h2>
|
||||
<div className="tabs">
|
||||
<button
|
||||
type="button"
|
||||
className={tab === "strategy" ? "tab active" : "tab"}
|
||||
onClick={() => setTab("strategy")}
|
||||
>
|
||||
策略设置
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={tab === "account" ? "tab active" : "tab"}
|
||||
onClick={() => setTab("account")}
|
||||
>
|
||||
登录账户
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<h2 style={{ marginTop: 0 }}>登录账号</h2>
|
||||
{err ? <div className="err">{err}</div> : null}
|
||||
{ok ? <div style={{ color: "var(--up)", marginBottom: 12 }}>{ok}</div> : null}
|
||||
<form onSubmit={onSaveCreds}>
|
||||
<div className="field">
|
||||
<label htmlFor="user">新用户名</label>
|
||||
<input
|
||||
id="user"
|
||||
value={newUsername}
|
||||
onChange={(e) => setNewUsername(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cur">当前密码</label>
|
||||
<input
|
||||
id="cur"
|
||||
type="password"
|
||||
value={currentPassword}
|
||||
onChange={(e) => setCurrentPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="np">新密码</label>
|
||||
<input
|
||||
id="np"
|
||||
type="password"
|
||||
value={newPassword}
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cp">确认新密码</label>
|
||||
<input
|
||||
id="cp"
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button className="btn" type="submit" disabled={loading}>
|
||||
{loading ? "保存中…" : "保存账号"}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{tab === "strategy" ? (
|
||||
<div className="card">
|
||||
<p style={{ color: "var(--muted)", marginTop: 0 }}>
|
||||
标的波动 N 点全平、轮次休息、费率(滑点=1×费率)。
|
||||
</p>
|
||||
{stratOk ? <div style={{ color: "var(--up)", marginBottom: 12 }}>{stratOk}</div> : null}
|
||||
{err && tab === "strategy" ? <div className="err">{err}</div> : null}
|
||||
<form onSubmit={onSaveStrategy}>
|
||||
<div className="field">
|
||||
<label htmlFor="exit">EXIT_MOVE_POINTS(标的波动点数)</label>
|
||||
<input
|
||||
id="exit"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={exitPts}
|
||||
onChange={(e) => setExitPts(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="rest">REST_SECONDS(轮间休息秒)</label>
|
||||
<input
|
||||
id="rest"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={rest}
|
||||
onChange={(e) => setRest(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="rounds">MAX_ROUNDS</label>
|
||||
<input
|
||||
id="rounds"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={maxRounds}
|
||||
onChange={(e) => setMaxRounds(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="fee">FEE_RATE</label>
|
||||
<input
|
||||
id="fee"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.0001"
|
||||
value={fee}
|
||||
onChange={(e) => setFee(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<button className="btn" type="submit">
|
||||
保存策略
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
) : (
|
||||
<div className="card">
|
||||
{err ? <div className="err">{err}</div> : null}
|
||||
{ok ? <div style={{ color: "var(--up)", marginBottom: 12 }}>{ok}</div> : null}
|
||||
<form onSubmit={onSaveCreds}>
|
||||
<div className="field">
|
||||
<label htmlFor="user">新用户名</label>
|
||||
<input
|
||||
id="user"
|
||||
value={newUsername}
|
||||
onChange={(e) => setNewUsername(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cur">当前密码</label>
|
||||
<input
|
||||
id="cur"
|
||||
type="password"
|
||||
value={currentPassword}
|
||||
onChange={(e) => setCurrentPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="np">新密码</label>
|
||||
<input
|
||||
id="np"
|
||||
type="password"
|
||||
value={newPassword}
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cp">确认新密码</label>
|
||||
<input
|
||||
id="cp"
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button className="btn" type="submit" disabled={loading}>
|
||||
{loading ? "保存中…" : "保存账号"}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user