Show open time and hold duration on position cards.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -238,6 +238,7 @@ export type PlanState = {
|
||||
position: {
|
||||
has_position: boolean;
|
||||
group_id?: string;
|
||||
open_at_ms?: number | null;
|
||||
perp_side?: string;
|
||||
option_side?: string;
|
||||
perp_inst_id?: string;
|
||||
|
||||
@@ -41,6 +41,33 @@ function formatCountdown(msLeft: number): string {
|
||||
return `${m}分 ${String(sec).padStart(2, "0")}秒`;
|
||||
}
|
||||
|
||||
/** 上海时区开仓时间 */
|
||||
function fmtOpenTime(ms: number | null | undefined) {
|
||||
if (ms == null || !Number.isFinite(ms) || ms <= 0) return "—";
|
||||
return new Date(ms).toLocaleString("zh-CN", {
|
||||
timeZone: "Asia/Shanghai",
|
||||
hour12: false,
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
/** 持仓时长(实时) */
|
||||
function fmtHoldDuration(openAtMs: number | null | undefined, now: number) {
|
||||
if (openAtMs == null || !Number.isFinite(openAtMs) || openAtMs <= 0) return "—";
|
||||
const ms = Math.max(0, now - openAtMs);
|
||||
const totalSec = Math.floor(ms / 1000);
|
||||
const h = Math.floor(totalSec / 3600);
|
||||
const m = Math.floor((totalSec % 3600) / 60);
|
||||
const s = totalSec % 60;
|
||||
if (h > 0) return `${h}时${m}分${s}秒`;
|
||||
if (m > 0) return `${m}分${s}秒`;
|
||||
return `${s}秒`;
|
||||
}
|
||||
|
||||
const PHASE_ZH: Record<string, string> = {
|
||||
idle: "空闲",
|
||||
wait_signal: "等待信号",
|
||||
@@ -132,6 +159,9 @@ export default function PlanPage() {
|
||||
plan?.mode === "LIVE"
|
||||
? `实盘·${(snap?.exchange || "okx").toUpperCase()}`
|
||||
: "模拟盘";
|
||||
const openAtMs = pos?.open_at_ms ?? null;
|
||||
const openTimeLabel = fmtOpenTime(openAtMs);
|
||||
const holdDurationLabel = open ? fmtHoldDuration(openAtMs, nowMs) : "—";
|
||||
|
||||
return (
|
||||
<div className="plan-page">
|
||||
@@ -429,6 +459,14 @@ export default function PlanPage() {
|
||||
<span className="pos-label">波动比例</span>
|
||||
<span className="pos-value mono">{fmt(movePct, 2)}%</span>
|
||||
</div>
|
||||
<div className="pos-cell">
|
||||
<span className="pos-label">开仓时间</span>
|
||||
<span className="pos-value mono">{openTimeLabel}</span>
|
||||
</div>
|
||||
<div className="pos-cell">
|
||||
<span className="pos-label">持仓时长</span>
|
||||
<span className="pos-value mono">{holdDurationLabel}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -482,6 +520,14 @@ export default function PlanPage() {
|
||||
<span className="pos-label">初始权利金</span>
|
||||
<span className="pos-value mono">{fmt(pos?.initial_premium)}</span>
|
||||
</div>
|
||||
<div className="pos-cell">
|
||||
<span className="pos-label">开仓时间</span>
|
||||
<span className="pos-value mono">{openTimeLabel}</span>
|
||||
</div>
|
||||
<div className="pos-cell">
|
||||
<span className="pos-label">持仓时长</span>
|
||||
<span className="pos-value mono">{holdDurationLabel}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user