1
This commit is contained in:
parent
8cb4ad9762
commit
2779330ee5
@ -975,6 +975,91 @@
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.signal-feed-grid {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.signal-feed-card {
|
||||
padding: 14px 16px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
border: 1px solid rgba(255,255,255,0.06);
|
||||
}
|
||||
|
||||
.signal-feed-card.buy {
|
||||
border-color: rgba(48, 209, 88, 0.18);
|
||||
background: rgba(48, 209, 88, 0.07);
|
||||
}
|
||||
|
||||
.signal-feed-card.sell {
|
||||
border-color: rgba(255, 111, 97, 0.18);
|
||||
background: rgba(255, 111, 97, 0.07);
|
||||
}
|
||||
|
||||
.signal-feed-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.signal-feed-symbol {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.signal-feed-meta {
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.signal-feed-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.signal-feed-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.signal-feed-stat {
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
}
|
||||
|
||||
.signal-feed-stat .label {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 10px;
|
||||
margin-bottom: 4px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
}
|
||||
|
||||
.signal-feed-stat .value {
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.signal-feed-reason {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.workspace-stream {
|
||||
min-height: 0;
|
||||
}
|
||||
@ -1673,6 +1758,101 @@
|
||||
background: rgba(255,255,255,0.02);
|
||||
}
|
||||
|
||||
.position-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.position-card {
|
||||
padding: 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
border: 1px solid rgba(255,255,255,0.06);
|
||||
}
|
||||
|
||||
.position-card.long {
|
||||
border-color: rgba(48, 209, 88, 0.18);
|
||||
}
|
||||
|
||||
.position-card.short {
|
||||
border-color: rgba(255, 111, 97, 0.18);
|
||||
}
|
||||
|
||||
.position-card-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.position-card-symbol {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.position-card-meta {
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.position-card-pnl {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.position-card-pnl .amount {
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.position-card-pnl .ratio {
|
||||
margin-top: 4px;
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.position-card-gridline {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.position-card-block {
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
}
|
||||
|
||||
.position-card-block .label {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 10px;
|
||||
margin-bottom: 4px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
}
|
||||
|
||||
.position-card-block .value {
|
||||
font-family: "IBM Plex Mono", monospace;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.position-card-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.unified-table table {
|
||||
min-width: 980px;
|
||||
}
|
||||
@ -1771,12 +1951,15 @@
|
||||
.platform-grid,
|
||||
.signal-grid,
|
||||
.ops-grid,
|
||||
.coord-grid {
|
||||
.coord-grid,
|
||||
.position-card-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.platform-overview,
|
||||
.platform-stats {
|
||||
.platform-stats,
|
||||
.signal-feed-stats,
|
||||
.position-card-gridline {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
@ -1807,6 +1990,8 @@
|
||||
.hero-metrics,
|
||||
.platform-stats,
|
||||
.platform-overview,
|
||||
.signal-feed-stats,
|
||||
.position-card-gridline,
|
||||
.signal-stats,
|
||||
.heartbeat-grid,
|
||||
.health-ribbon,
|
||||
@ -2817,17 +3002,46 @@
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = signals.map((signal) => `
|
||||
<div class="stream-item">
|
||||
<div class="time">${relativeTime(signal.created_at)}<br>${formatTime(signal.created_at)}</div>
|
||||
<div class="headline">
|
||||
<strong>${signal.symbol || '-'}</strong>
|
||||
${signal.action === 'buy' ? '做多' : signal.action === 'sell' ? '做空' : '观望'}
|
||||
<span style="color: var(--muted);">| ${signal.signal_type || '-'} | ${signal.timeframe || signal.type || '-'}</span>
|
||||
container.innerHTML = `
|
||||
<div class="signal-feed-grid">
|
||||
${signals.slice(0, 5).map((signal) => `
|
||||
<article class="signal-feed-card ${signal.action || 'wait'}">
|
||||
<div class="signal-feed-head">
|
||||
<div>
|
||||
<div class="signal-feed-symbol">${signal.symbol || '-'}</div>
|
||||
<div class="signal-feed-meta">${relativeTime(signal.created_at)} / ${formatTime(signal.created_at)}</div>
|
||||
</div>
|
||||
<div class="grade">${signal.grade || '-'} / ${formatPercent(signal.confidence || 0, 1)}</div>
|
||||
<span class="badge ${statusClassFromAction(signal.action)}">${signal.action === 'buy' ? '做多' : signal.action === 'sell' ? '做空' : '观望'}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
<div class="signal-feed-tags">
|
||||
<span class="event-inline-badge">${signal.signal_type || '-'}</span>
|
||||
<span class="event-inline-badge">${signal.timeframe || signal.type || '-'}</span>
|
||||
${signal.grade ? `<span class="event-inline-badge">${signal.grade}</span>` : ''}
|
||||
${signal.setup_type ? `<span class="event-inline-badge">${signal.setup_type}</span>` : ''}
|
||||
</div>
|
||||
<div class="signal-feed-stats">
|
||||
<div class="signal-feed-stat">
|
||||
<span class="label">信心度</span>
|
||||
<span class="value">${formatPercent(signal.confidence || 0, 1)}</span>
|
||||
</div>
|
||||
<div class="signal-feed-stat">
|
||||
<span class="label">价格</span>
|
||||
<span class="value">入场 ${formatMoney(signal.entry_price)} / 现价 ${formatMoney(signal.current_price)}</span>
|
||||
</div>
|
||||
<div class="signal-feed-stat">
|
||||
<span class="label">止盈止损</span>
|
||||
<span class="value">${formatMoney(signal.take_profit)} / ${formatMoney(signal.stop_loss)}</span>
|
||||
</div>
|
||||
<div class="signal-feed-stat">
|
||||
<span class="label">仓位 / 入场方式</span>
|
||||
<span class="value">${signal.position_size || '-'} / ${signal.entry_type || '-'}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="signal-feed-reason">${signal.reasoning || signal.reason || signal.summary || '暂无详细分析理由'}</div>
|
||||
</article>
|
||||
`).join('')}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderAgentSignals(cryptoAgent, signalStats) {
|
||||
@ -3280,40 +3494,45 @@
|
||||
}
|
||||
|
||||
container.innerHTML = `
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>平台</th>
|
||||
<th>账号</th>
|
||||
<th>交易对</th>
|
||||
<th>方向</th>
|
||||
<th>入场 / 现价</th>
|
||||
<th>仓位 / 杠杆</th>
|
||||
<th>Setup</th>
|
||||
<th>止盈 / 止损</th>
|
||||
<th>未实现盈亏</th>
|
||||
<th>盈亏比例</th>
|
||||
<th>时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<div class="position-card-grid">
|
||||
${total.map((item) => `
|
||||
<tr>
|
||||
<td><span class="platform-pill">${item.platform}</span></td>
|
||||
<td class="inline-mono">${item.account_id || '-'}</td>
|
||||
<td><strong>${item.symbol || '-'}</strong></td>
|
||||
<td><span class="side-pill ${item.side === 'long' ? 'long' : 'short'}">${item.side === 'long' ? 'long' : 'short'}</span></td>
|
||||
<td class="inline-mono">${formatMoney(item.entry_price)} / ${formatMoney(item.mark_price)}</td>
|
||||
<td class="inline-mono">${formatNumber(item.size, 4)} / ${formatNumber(item.leverage, 1)}x</td>
|
||||
<td>${item.setup_type ? `<div class="inline-mono">${item.setup_type}</div><div class="analysis-log-detail">${item.entry_basis || item.setup_basis || '-'}</div>` : '-'}</td>
|
||||
<td class="inline-mono">${item.take_profit ? formatMoney(item.take_profit) : '-'} / ${item.stop_loss ? formatMoney(item.stop_loss) : '-'}</td>
|
||||
<td style="color:${(item.unrealized_pnl || 0) >= 0 ? 'var(--good)' : 'var(--danger)'}">${formatMoney(item.unrealized_pnl)}</td>
|
||||
<td style="color:${(item.pnl_percent || 0) >= 0 ? 'var(--good)' : 'var(--danger)'}">${formatPercent(item.pnl_percent, 2)}</td>
|
||||
<td class="inline-mono">${item.opened_at ? relativeTime(item.opened_at) : '-'}</td>
|
||||
</tr>
|
||||
<article class="position-card ${item.side === 'long' ? 'long' : 'short'}">
|
||||
<div class="position-card-head">
|
||||
<div>
|
||||
<div class="position-card-symbol">${item.symbol || '-'}</div>
|
||||
<div class="position-card-meta">${item.platform || '-'} / ${item.account_id || '-'} / ${item.opened_at ? `${relativeTime(item.opened_at)} / ${formatTime(item.opened_at)}` : '-'}</div>
|
||||
</div>
|
||||
<div class="position-card-pnl">
|
||||
<div class="amount" style="color:${(item.unrealized_pnl || 0) >= 0 ? 'var(--good)' : 'var(--danger)'}">${formatMoney(item.unrealized_pnl)}</div>
|
||||
<div class="ratio" style="color:${(item.pnl_percent || 0) >= 0 ? 'var(--good)' : 'var(--danger)'}">${formatPercent(item.pnl_percent, 2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-card-tags">
|
||||
<span class="platform-pill">${item.platform}</span>
|
||||
<span class="side-pill ${item.side === 'long' ? 'long' : 'short'}">${item.side === 'long' ? 'long' : 'short'}</span>
|
||||
${item.setup_type ? `<span class="event-inline-badge">${item.setup_type}</span>` : ''}
|
||||
</div>
|
||||
<div class="position-card-gridline">
|
||||
<div class="position-card-block">
|
||||
<span class="label">入场 / 现价</span>
|
||||
<span class="value">${formatMoney(item.entry_price)} / ${formatMoney(item.mark_price)}</span>
|
||||
</div>
|
||||
<div class="position-card-block">
|
||||
<span class="label">仓位 / 杠杆</span>
|
||||
<span class="value">${formatNumber(item.size, 4)} / ${formatNumber(item.leverage, 1)}x</span>
|
||||
</div>
|
||||
<div class="position-card-block">
|
||||
<span class="label">止盈 / 止损</span>
|
||||
<span class="value">${item.take_profit ? formatMoney(item.take_profit) : '-'} / ${item.stop_loss ? formatMoney(item.stop_loss) : '-'}</span>
|
||||
</div>
|
||||
<div class="position-card-block">
|
||||
<span class="label">Setup / Entry</span>
|
||||
<span class="value">${item.setup_type || '-'}${item.entry_basis || item.setup_basis ? `<br>${item.entry_basis || item.setup_basis}` : ''}</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
`).join('')}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user