Improve dashboard risk card styling, colors, and add risk control docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -75,10 +75,26 @@
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.dashboard-risk-heading {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.dash-risk-doc-ref {
|
||||
font-size: 0.72rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.dash-risk-doc-ref code {
|
||||
font-size: 0.68rem;
|
||||
}
|
||||
|
||||
.dashboard-risk-item {
|
||||
flex: 1 1 0;
|
||||
min-width: 5.8rem;
|
||||
padding: 0.45rem 0.55rem;
|
||||
min-width: 6.4rem;
|
||||
padding: 0.5rem 0.6rem;
|
||||
text-align: center;
|
||||
border-right: 1px solid var(--table-border);
|
||||
}
|
||||
@@ -88,21 +104,71 @@
|
||||
}
|
||||
|
||||
.dashboard-risk-label {
|
||||
font-size: 0.62rem;
|
||||
line-height: 1.3;
|
||||
font-size: 0.74rem;
|
||||
line-height: 1.35;
|
||||
color: var(--text-muted);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dashboard-risk-value {
|
||||
font-size: 0.8rem;
|
||||
font-size: 0.92rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-title);
|
||||
margin-top: 0.18rem;
|
||||
margin-top: 0.22rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dashboard-risk-value.risk-switch-on {
|
||||
color: var(--profit);
|
||||
}
|
||||
|
||||
.dashboard-risk-value.risk-switch-off {
|
||||
color: var(--loss);
|
||||
}
|
||||
|
||||
.dashboard-risk-value.risk-cap-single {
|
||||
color: #5eb8ff;
|
||||
}
|
||||
|
||||
[data-theme="light"] .dashboard-risk-value.risk-cap-single {
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
.dashboard-risk-value.risk-cap-roll {
|
||||
color: #c4a035;
|
||||
}
|
||||
|
||||
[data-theme="light"] .dashboard-risk-value.risk-cap-roll {
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.dashboard-risk-value .risk-margin-safe {
|
||||
color: var(--profit);
|
||||
}
|
||||
|
||||
.dashboard-risk-value .risk-margin-warn {
|
||||
color: var(--planned-text);
|
||||
}
|
||||
|
||||
.dashboard-risk-value .risk-margin-over {
|
||||
color: var(--loss);
|
||||
}
|
||||
|
||||
.dashboard-risk-value .risk-margin-sep {
|
||||
color: var(--text-muted);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.dashboard-risk-value .risk-margin-cap-inline {
|
||||
color: #5eb8ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
[data-theme="light"] .dashboard-risk-value .risk-margin-cap-inline {
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
.dashboard-risk-grid .stat-item {
|
||||
min-width: 5.5rem;
|
||||
}
|
||||
@@ -131,10 +197,21 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.dashboard-table .badge.dir {
|
||||
.dashboard-table .badge.dir-long,
|
||||
.dashboard-table .badge.dir-short {
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.dashboard-table .badge.dir-long {
|
||||
background: var(--profit-bg);
|
||||
color: var(--profit);
|
||||
}
|
||||
|
||||
.dashboard-table .badge.dir-short {
|
||||
background: var(--loss-bg);
|
||||
color: var(--loss);
|
||||
}
|
||||
|
||||
.dashboard-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
+54
-18
@@ -100,8 +100,40 @@
|
||||
}
|
||||
|
||||
function directionBadgeHtml(row) {
|
||||
var label = row.direction_label || (row.direction === 'short' ? '做空' : '做多');
|
||||
return '<span class="badge dir">' + escHtml(label) + '</span>';
|
||||
var dir = (row.direction || 'long').toString().toLowerCase();
|
||||
var label = row.direction_label || (dir === 'short' ? '做空' : '做多');
|
||||
var cls = dir === 'short' ? 'dir dir-short' : 'dir dir-long';
|
||||
return '<span class="badge ' + cls + '">' + escHtml(label) + '</span>';
|
||||
}
|
||||
|
||||
function riskMarginPctHtml(used, limit) {
|
||||
if (used == null) return escHtml('—');
|
||||
var usedCls = 'risk-margin-safe';
|
||||
if (limit != null && limit > 0) {
|
||||
var ratio = Number(used) / Number(limit);
|
||||
if (ratio >= 1) usedCls = 'risk-margin-over';
|
||||
else if (ratio >= 0.85) usedCls = 'risk-margin-warn';
|
||||
}
|
||||
var html = '<span class="' + usedCls + '">' + escHtml(fmtNum(used) + '%') + '</span>';
|
||||
if (limit != null) {
|
||||
html += ' <span class="risk-margin-sep">/</span> ' +
|
||||
'<span class="risk-margin-cap-inline">' + escHtml(fmtNum(limit) + '%') + '</span>';
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderRiskGrid(items) {
|
||||
if (!riskGridEl) return;
|
||||
riskGridEl.innerHTML = items.map(function (it) {
|
||||
var val = it.valueHtml != null ? it.valueHtml : escHtml(it.value);
|
||||
var cls = 'dashboard-risk-value' + (it.valueClass ? ' ' + it.valueClass : '');
|
||||
return (
|
||||
'<div class="dashboard-risk-item">' +
|
||||
'<div class="dashboard-risk-label">' + escHtml(it.label) + '</div>' +
|
||||
'<div class="' + cls + '">' + val + '</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function fmtHours(h) {
|
||||
@@ -164,10 +196,6 @@
|
||||
}
|
||||
var marginPct = risk.margin_pct_used;
|
||||
var maxMarginPct = lim.max_margin_pct;
|
||||
var marginPctText = marginPct != null ? fmtNum(marginPct) + '%' : '—';
|
||||
if (maxMarginPct != null && marginPct != null) {
|
||||
marginPctText += ' / ' + fmtNum(maxMarginPct) + '%';
|
||||
}
|
||||
|
||||
if (riskReasonEl) {
|
||||
var reason = st.reason || (enabled ? '可新开仓' : '风控已关闭');
|
||||
@@ -185,7 +213,11 @@
|
||||
}
|
||||
|
||||
var items = [
|
||||
{ label: '风控开关', value: enabled ? '开启' : '关闭' },
|
||||
{
|
||||
label: '风控开关',
|
||||
value: enabled ? '开启' : '关闭',
|
||||
valueClass: enabled ? 'risk-switch-on' : 'risk-switch-off',
|
||||
},
|
||||
{ label: '持仓限制', value: active + ' / ' + (maxPos != null ? maxPos : '—') },
|
||||
{ label: '日持仓限制', value: dailyOpens + ' / ' + (dailyPosLim != null ? dailyPosLim : '—') },
|
||||
{ label: '日交易风险', value: dailyRiskText },
|
||||
@@ -193,21 +225,25 @@
|
||||
{ label: '冷静期(默认)', value: fmtHours(lim.cooling_hours_manual) },
|
||||
{ label: '复盘后冷静', value: fmtHours(lim.cooling_hours_manual_journal) },
|
||||
{ label: '冷静剩余', value: fmtRemainSec(st.freeze_remaining_sec) },
|
||||
{ label: '保证金占比', value: marginPctText },
|
||||
{ label: '保证金上限', value: maxMarginPct != null ? fmtNum(maxMarginPct) + '%' : '—' },
|
||||
{ label: '综合保证金上限', value: lim.roll_max_margin_pct != null ? fmtNum(lim.roll_max_margin_pct) + '%' : '—' },
|
||||
{
|
||||
label: '综合保证金占比',
|
||||
valueHtml: riskMarginPctHtml(marginPct, maxMarginPct),
|
||||
},
|
||||
{
|
||||
label: '单仓保证金上限',
|
||||
value: maxMarginPct != null ? fmtNum(maxMarginPct) + '%' : '—',
|
||||
valueClass: 'risk-cap-single',
|
||||
},
|
||||
{
|
||||
label: '综合保证金上限',
|
||||
value: lim.roll_max_margin_pct != null ? fmtNum(lim.roll_max_margin_pct) + '%' : '—',
|
||||
valueClass: 'risk-cap-roll',
|
||||
},
|
||||
{ label: '计仓模式', value: sizingDetail },
|
||||
{ label: '交易日切', value: lim.trading_day_reset_hour != null ? lim.trading_day_reset_hour + ':00' : '—' }
|
||||
];
|
||||
|
||||
riskGridEl.innerHTML = items.map(function (it) {
|
||||
return (
|
||||
'<div class="dashboard-risk-item">' +
|
||||
'<div class="dashboard-risk-label">' + escHtml(it.label) + '</div>' +
|
||||
'<div class="dashboard-risk-value">' + escHtml(it.value) + '</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}).join('');
|
||||
renderRiskGrid(items);
|
||||
}
|
||||
|
||||
function updateCtpBadge(st) {
|
||||
|
||||
Reference in New Issue
Block a user