Show open time and hold duration on position cards.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-29 15:41:56 +08:00
parent 195e63fb2e
commit 3df64aeb2d
4 changed files with 58 additions and 0 deletions
+1
View File
@@ -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;
+46
View File
@@ -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>
</>