a
This commit is contained in:
parent
9513f94760
commit
3a07c55281
|
|
@ -243,79 +243,156 @@ const TradeList = () => {
|
||||||
<th>交易对</th>
|
<th>交易对</th>
|
||||||
<th>方向</th>
|
<th>方向</th>
|
||||||
<th>数量</th>
|
<th>数量</th>
|
||||||
|
<th>保证金</th>
|
||||||
<th>入场价</th>
|
<th>入场价</th>
|
||||||
<th>出场价</th>
|
<th>出场价</th>
|
||||||
<th>盈亏</th>
|
<th>盈亏</th>
|
||||||
|
<th>盈亏比例</th>
|
||||||
<th>状态</th>
|
<th>状态</th>
|
||||||
<th>平仓类型</th>
|
<th>平仓类型</th>
|
||||||
<th>时间</th>
|
<th>时间</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{trades.map(trade => (
|
{trades.map(trade => {
|
||||||
<tr key={trade.id}>
|
// 计算保证金:如果有entry_value_usdt和leverage,则计算;否则使用名义价值/杠杆
|
||||||
<td>{trade.symbol}</td>
|
const entryValue = trade.entry_value_usdt !== undefined
|
||||||
<td className={trade.side === 'BUY' ? 'buy' : 'sell'}>{trade.side}</td>
|
? parseFloat(trade.entry_value_usdt)
|
||||||
<td>{parseFloat(trade.quantity).toFixed(4)}</td>
|
: (parseFloat(trade.quantity || 0) * parseFloat(trade.entry_price || 0))
|
||||||
<td>{parseFloat(trade.entry_price).toFixed(4)}</td>
|
const leverage = parseFloat(trade.leverage || 10)
|
||||||
<td>{trade.exit_price ? parseFloat(trade.exit_price).toFixed(4) : '-'}</td>
|
const margin = leverage > 0 ? entryValue / leverage : 0
|
||||||
<td className={parseFloat(trade.pnl) >= 0 ? 'positive' : 'negative'}>
|
|
||||||
{parseFloat(trade.pnl).toFixed(2)} USDT
|
// 计算盈亏比例(盈亏/保证金)
|
||||||
</td>
|
const pnl = parseFloat(trade.pnl || 0)
|
||||||
<td>
|
const pnlPercent = margin > 0 ? (pnl / margin) * 100 : 0
|
||||||
<span className={`status ${trade.status}`}>{trade.status === 'open' ? '持仓中' : trade.status === 'closed' ? '已平仓' : '已取消'}</span>
|
|
||||||
</td>
|
// 格式化时间为北京时间
|
||||||
<td>{trade.exit_reason_display || '-'}</td>
|
const formatTime = (timeStr) => {
|
||||||
<td>{new Date(trade.entry_time).toLocaleString('zh-CN')}</td>
|
if (!timeStr) return '-'
|
||||||
</tr>
|
try {
|
||||||
))}
|
const date = new Date(timeStr)
|
||||||
|
if (isNaN(date.getTime())) return timeStr
|
||||||
|
return date.toLocaleString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
timeZone: 'Asia/Shanghai'
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
return timeStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr key={trade.id}>
|
||||||
|
<td>{trade.symbol}</td>
|
||||||
|
<td className={trade.side === 'BUY' ? 'buy' : 'sell'}>{trade.side}</td>
|
||||||
|
<td>{parseFloat(trade.quantity).toFixed(4)}</td>
|
||||||
|
<td>{margin.toFixed(2)} USDT</td>
|
||||||
|
<td>{parseFloat(trade.entry_price).toFixed(4)}</td>
|
||||||
|
<td>{trade.exit_price ? parseFloat(trade.exit_price).toFixed(4) : '-'}</td>
|
||||||
|
<td className={pnl >= 0 ? 'positive' : 'negative'}>
|
||||||
|
{pnl.toFixed(2)} USDT
|
||||||
|
</td>
|
||||||
|
<td className={pnlPercent >= 0 ? 'positive' : 'negative'}>
|
||||||
|
{pnlPercent >= 0 ? '+' : ''}{pnlPercent.toFixed(2)}%
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span className={`status ${trade.status}`}>{trade.status === 'open' ? '持仓中' : trade.status === 'closed' ? '已平仓' : '已取消'}</span>
|
||||||
|
</td>
|
||||||
|
<td>{trade.exit_reason_display || '-'}</td>
|
||||||
|
<td>{formatTime(trade.entry_time)}</td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
{/* 移动端卡片 */}
|
{/* 移动端卡片 */}
|
||||||
<div className="trades-cards">
|
<div className="trades-cards">
|
||||||
{trades.map(trade => (
|
{trades.map(trade => {
|
||||||
<div key={trade.id} className="trade-card">
|
// 计算保证金和盈亏比例
|
||||||
<div className="trade-card-header">
|
const entryValue = trade.entry_value_usdt !== undefined
|
||||||
<span className="trade-card-symbol">{trade.symbol}</span>
|
? parseFloat(trade.entry_value_usdt)
|
||||||
<span className={`trade-card-side ${trade.side === 'BUY' ? 'buy' : 'sell'} status ${trade.status}`}>
|
: (parseFloat(trade.quantity || 0) * parseFloat(trade.entry_price || 0))
|
||||||
{trade.side === 'BUY' ? '买入' : '卖出'} · {trade.status === 'open' ? '持仓中' : trade.status === 'closed' ? '已平仓' : '已取消'}
|
const leverage = parseFloat(trade.leverage || 10)
|
||||||
</span>
|
const margin = leverage > 0 ? entryValue / leverage : 0
|
||||||
</div>
|
const pnl = parseFloat(trade.pnl || 0)
|
||||||
<div className="trade-card-body">
|
const pnlPercent = margin > 0 ? (pnl / margin) * 100 : 0
|
||||||
<div className="trade-card-field">
|
|
||||||
<span className="trade-card-label">数量</span>
|
// 格式化时间为北京时间
|
||||||
<span className="trade-card-value">{parseFloat(trade.quantity).toFixed(4)}</span>
|
const formatTime = (timeStr) => {
|
||||||
</div>
|
if (!timeStr) return '-'
|
||||||
<div className="trade-card-field">
|
try {
|
||||||
<span className="trade-card-label">入场价</span>
|
const date = new Date(timeStr)
|
||||||
<span className="trade-card-value">{parseFloat(trade.entry_price).toFixed(4)}</span>
|
if (isNaN(date.getTime())) return timeStr
|
||||||
</div>
|
return date.toLocaleString('zh-CN', {
|
||||||
<div className="trade-card-field">
|
month: '2-digit',
|
||||||
<span className="trade-card-label">出场价</span>
|
day: '2-digit',
|
||||||
<span className="trade-card-value">{trade.exit_price ? parseFloat(trade.exit_price).toFixed(4) : '-'}</span>
|
hour: '2-digit',
|
||||||
</div>
|
minute: '2-digit',
|
||||||
<div className="trade-card-field">
|
timeZone: 'Asia/Shanghai'
|
||||||
<span className="trade-card-label">盈亏</span>
|
})
|
||||||
<span className={`trade-card-value ${parseFloat(trade.pnl) >= 0 ? 'positive' : 'negative'}`}>
|
} catch (e) {
|
||||||
{parseFloat(trade.pnl).toFixed(2)} USDT
|
return timeStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={trade.id} className="trade-card">
|
||||||
|
<div className="trade-card-header">
|
||||||
|
<span className="trade-card-symbol">{trade.symbol}</span>
|
||||||
|
<span className={`trade-card-side ${trade.side === 'BUY' ? 'buy' : 'sell'} status ${trade.status}`}>
|
||||||
|
{trade.side === 'BUY' ? '买入' : '卖出'} · {trade.status === 'open' ? '持仓中' : trade.status === 'closed' ? '已平仓' : '已取消'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{trade.exit_reason_display && (
|
<div className="trade-card-body">
|
||||||
<div className="trade-card-field">
|
<div className="trade-card-field">
|
||||||
<span className="trade-card-label">平仓类型</span>
|
<span className="trade-card-label">数量</span>
|
||||||
<span className="trade-card-value">{trade.exit_reason_display}</span>
|
<span className="trade-card-value">{parseFloat(trade.quantity).toFixed(4)}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className="trade-card-field">
|
||||||
|
<span className="trade-card-label">保证金</span>
|
||||||
|
<span className="trade-card-value">{margin.toFixed(2)} USDT</span>
|
||||||
|
</div>
|
||||||
|
<div className="trade-card-field">
|
||||||
|
<span className="trade-card-label">入场价</span>
|
||||||
|
<span className="trade-card-value">{parseFloat(trade.entry_price).toFixed(4)}</span>
|
||||||
|
</div>
|
||||||
|
<div className="trade-card-field">
|
||||||
|
<span className="trade-card-label">出场价</span>
|
||||||
|
<span className="trade-card-value">{trade.exit_price ? parseFloat(trade.exit_price).toFixed(4) : '-'}</span>
|
||||||
|
</div>
|
||||||
|
<div className="trade-card-field">
|
||||||
|
<span className="trade-card-label">盈亏</span>
|
||||||
|
<span className={`trade-card-value ${pnl >= 0 ? 'positive' : 'negative'}`}>
|
||||||
|
{pnl.toFixed(2)} USDT
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="trade-card-field">
|
||||||
|
<span className="trade-card-label">盈亏比例</span>
|
||||||
|
<span className={`trade-card-value ${pnlPercent >= 0 ? 'positive' : 'negative'}`}>
|
||||||
|
{pnlPercent >= 0 ? '+' : ''}{pnlPercent.toFixed(2)}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{trade.exit_reason_display && (
|
||||||
|
<div className="trade-card-field">
|
||||||
|
<span className="trade-card-label">平仓类型</span>
|
||||||
|
<span className="trade-card-value">{trade.exit_reason_display}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="trade-card-footer">
|
||||||
|
<span>{formatTime(trade.entry_time)}</span>
|
||||||
|
{trade.exit_time && (
|
||||||
|
<span>平仓: {formatTime(trade.exit_time)}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="trade-card-footer">
|
)
|
||||||
<span>{new Date(trade.entry_time).toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })}</span>
|
})}
|
||||||
{trade.exit_time && (
|
|
||||||
<span>平仓: {new Date(trade.exit_time).toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,24 @@ function RecommendationsViewer() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatTime = (timeStr) => {
|
const formatTime = (timeStr) => {
|
||||||
|
if (!timeStr) return '-'
|
||||||
|
try {
|
||||||
|
const date = new Date(timeStr)
|
||||||
|
if (isNaN(date.getTime())) return timeStr
|
||||||
|
// 使用北京时间格式化
|
||||||
|
return date.toLocaleString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
timeZone: 'Asia/Shanghai' // 明确使用北京时间
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
return timeStr
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!timeStr) return '-';
|
if (!timeStr) return '-';
|
||||||
try {
|
try {
|
||||||
const date = new Date(timeStr);
|
const date = new Date(timeStr);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user