Skip to content

Commit 10e5fdc

Browse files
refactor: 新增 24h 市场统计模块,优化 Header 与 StatsPanel 信息展示
- **新增 useMarketStats Hook**: - 计算 24h 价格变化、涨跌幅、成交量、高低价等市场统计指标 - 模拟资金费率(Funding Rate)与倒计时 - 提供 Mark Price 与 Index Price 计算逻辑 - **Header 组件重构**: - 新增 Binance 风格的 Ticker 信息栏,显示 24h 涨跌幅、高低价、成交量、资金费率等 - 新增 DevTools 模式切换
1 parent 97348f5 commit 10e5fdc

6 files changed

Lines changed: 488 additions & 200 deletions

File tree

src/App.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import DepthChart from './components/Dashboard/Chart/DepthChart';
1717
import { TradeForm, MobileTradebar } from './components/Dashboard/Trade';
1818
import { useUiStore } from './hooks/ui/useUiStore';
1919
import type { UiState } from './hooks/ui/useUiStore';
20+
import { useMarketStats } from './hooks/useMarketStats';
2021

2122
/* ============================================
2223
Constants
@@ -175,6 +176,13 @@ function App() {
175176
return () => clearTimeout(t);
176177
}, [isSwitching]);
177178

179+
// ========== 24h 市场统计 ==========
180+
const marketStats = useMarketStats({
181+
candleHistory,
182+
latestData,
183+
currentPrice: latestData?.price,
184+
});
185+
178186
// ========== 图表引用 ==========
179187
const chartRef = useRef<KLineChartHandle>(null);
180188

@@ -298,6 +306,7 @@ function App() {
298306
onDataSourceChange={handleDataSourceChange}
299307
connectionStatus={connectionStatus}
300308
isSwitching={isSwitching}
309+
marketStats={marketStats}
301310
/>
302311

303312
{/* ========== 主内容区域 ========== */}
@@ -421,9 +430,8 @@ function App() {
421430

422431
{/* Stats Panel - 单行 3 列 */}
423432
<StatsPanel
424-
latestData={latestData}
425433
analysisResult={analysisResult}
426-
priceColorClass={priceColorClass}
434+
marketStats={marketStats}
427435
/>
428436
</section>
429437

src/components/Dashboard/OrderBook.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ interface OrderRowProps {
101101

102102
/**
103103
* 订单行子组件
104-
* Binance 风格:3 列网格 + 深度背景条
104+
* Binance 风格:2 列网格 (Price | Amount) + 深度背景条
105105
*/
106106
function OrderRow({
107107
price,
@@ -135,10 +135,11 @@ function OrderRow({
135135
{price.toFixed(pricePrecision)}
136136
</span>
137137

138-
{/* 数量列 - 右对齐 */}
138+
{/* 数量列 - 右对齐,智能精度 */}
139139
<span className="relative z-10 font-mono text-[10px] md:text-[11px] tabular-nums text-right text-gray-400">
140-
{amount.toFixed(5)}
140+
{amount >= 1000 ? amount.toFixed(2) : amount >= 1 ? amount.toFixed(4) : amount.toFixed(5)}
141141
</span>
142+
142143
</div>
143144
);
144145
}

src/components/Dashboard/StatsPanel.tsx

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ interface StatCellProps {
1414
colorClass?: string;
1515
/** 副标签 */
1616
suffix?: string;
17+
/** 副标签颜色 */
18+
suffixColorClass?: string;
1719
}
1820

1921
/**
@@ -26,20 +28,21 @@ function StatCell({
2628
value,
2729
colorClass = 'text-white',
2830
suffix,
31+
suffixColorClass = 'text-gray-600',
2932
}: StatCellProps) {
3033
return (
31-
<div className="flex flex-col justify-center px-2 md:px-4 py-1 h-full">
34+
<div className="flex flex-col justify-center px-1.5 md:px-3 py-1 h-full min-w-20 md:min-w-0 shrink-0 md:shrink">
3235
<span className="text-[8px] md:text-[9px] text-gray-500 uppercase tracking-wider leading-none mb-0.5 md:mb-1">
3336
{label}
3437
</span>
3538
<div className="flex items-baseline gap-0.5 md:gap-1">
3639
<span
37-
className={`text-[clamp(12px,3vw,16px)] md:text-base font-bold font-mono tabular-nums leading-none ${colorClass}`}
40+
className={`text-[10px] md:text-xs font-bold font-mono tabular-nums leading-none ${colorClass}`}
3841
>
3942
{value}
4043
</span>
4144
{suffix && (
42-
<span className="text-[8px] md:text-[9px] text-gray-600 font-mono">
45+
<span className={`text-[8px] md:text-[9px] font-mono ${suffixColorClass}`}>
4346
{suffix}
4447
</span>
4548
)}
@@ -49,48 +52,75 @@ function StatCell({
4952
}
5053

5154
/* ============================================
52-
StatsPanel Component (高密度水平信息条)
55+
格式化工具
56+
============================================ */
57+
58+
function formatFundingCountdown(seconds: number): string {
59+
const h = Math.floor(seconds / 3600);
60+
const m = Math.floor((seconds % 3600) / 60);
61+
const s = seconds % 60;
62+
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
63+
}
64+
65+
/* ============================================
66+
StatsPanel Component (合约交易信息条)
5367
============================================ */
5468

5569
/**
56-
* Rust 分析信息条组件
57-
* 专业终端风格:单行 3 列布局,高密度数据展示
70+
* 合约交易信息条
71+
* Binance Futures 风格:单行 5 列布局
72+
* Mark Price / Index Price / Funding Rate / 24h Change / Spread
5873
*/
5974
function StatsPanel({
60-
latestData,
6175
analysisResult,
62-
priceColorClass,
76+
marketStats,
6377
}: StatsPanelProps) {
64-
/** 格式化 SMA5 显示值 */
65-
const formatSma5 = (): string => {
66-
const sma5 = analysisResult?.sma5;
67-
return sma5 != null ? `$${sma5.toFixed(2)}` : '--';
68-
};
78+
const changePercent = marketStats?.priceChangePercent ?? 0;
79+
const changeColor = changePercent >= 0 ? 'text-success' : 'text-danger';
80+
const changeSign = changePercent >= 0 ? '+' : '';
81+
6982
return (
7083
<div
7184
className="
7285
shrink-0 h-10 md:h-12 bg-bg-black border-t border-border-dark
73-
grid grid-cols-3 divide-x divide-border-dark
86+
flex md:grid md:grid-cols-5 divide-x divide-border-dark
87+
overflow-x-auto scrollbar-hide
7488
"
7589
>
76-
{/* Last Price */}
90+
{/* Mark Price */}
7791
<StatCell
78-
label="Last Price"
79-
value={`$${latestData?.price.toFixed(2) ?? '--'}`}
80-
colorClass={priceColorClass}
92+
label="Mark Price"
93+
value={`$${(marketStats?.markPrice ?? 0).toFixed(2)}`}
94+
colorClass="text-warning-alt"
8195
/>
8296

83-
{/* Spread */}
97+
{/* Index Price */}
8498
<StatCell
85-
label="Spread"
86-
value={`$${analysisResult?.spread?.toFixed(4) ?? '--'}`}
87-
colorClass="text-warning-alt"
99+
label="Index Price"
100+
value={`$${(marketStats?.indexPrice ?? 0).toFixed(2)}`}
101+
/>
102+
103+
{/* Funding Rate / Countdown */}
104+
<StatCell
105+
label="Funding / Countdown"
106+
value={`${((marketStats?.fundingRate ?? 0) * 100).toFixed(4)}%`}
107+
suffix={formatFundingCountdown(marketStats?.fundingCountdown ?? 0)}
108+
colorClass={(marketStats?.fundingRate ?? 0) >= 0 ? 'text-success' : 'text-danger'}
109+
suffixColorClass="text-warning-alt"
110+
/>
111+
112+
{/* 24h Change */}
113+
<StatCell
114+
label="24h Change"
115+
value={`${changeSign}${changePercent.toFixed(2)}%`}
116+
suffix={`${changeSign}${(marketStats?.priceChange ?? 0).toFixed(2)}`}
117+
colorClass={changeColor}
88118
/>
89119

90-
{/* SMA5 */}
120+
{/* Spread */}
91121
<StatCell
92-
label="SMA (5)"
93-
value={formatSma5()}
122+
label="Spread"
123+
value={`$${analysisResult?.spread?.toFixed(4) ?? '--'}`}
94124
colorClass="text-cyan"
95125
/>
96126
</div>

0 commit comments

Comments
 (0)