feat: 非交易时段禁开仓、移动保本与交易结果分类。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-25 13:33:17 +08:00
parent 598a1407e1
commit f31164076f
9 changed files with 387 additions and 49 deletions
+5 -1
View File
@@ -32,7 +32,11 @@
.market-hint{font-size:.7rem;margin-top:.25rem}
.trade-action-row{display:flex;flex-direction:column;gap:.45rem;margin:.85rem 0 .55rem}
.trade-action-row .btn-open{padding:.65rem .75rem;font-size:.9rem;width:100%}
.trade-action-row .btn-open:disabled{opacity:.65;cursor:wait}
.trade-action-row .btn-open:disabled{opacity:.45;cursor:not-allowed;filter:grayscale(.25)}
.trade-action-row .btn-open.btn-session-off{background:var(--text-muted);border-color:var(--text-muted)}
.trailing-be-toggle{display:flex;align-items:center;gap:.4rem;font-size:.78rem;color:var(--text-label);margin-bottom:.45rem;cursor:pointer;user-select:none}
.trailing-be-toggle input{width:auto;margin:0}
.session-hint{font-size:.72rem;margin:.35rem 0 0;text-align:center}
.trade-order-msg{font-size:.82rem;text-align:center;margin:0;padding:.35rem}
.trade-order-msg.ok{color:var(--profit)}
.trade-order-msg.err{color:var(--loss)}
+30 -3
View File
@@ -116,6 +116,18 @@
}
}
function updateSessionUi() {
var btnOpen = document.getElementById('btn-open');
var sessionHint = document.getElementById('session-hint');
if (btnOpen) {
btnOpen.disabled = !isTradingSession;
btnOpen.classList.toggle('btn-session-off', !isTradingSession);
}
if (sessionHint) {
sessionHint.hidden = !!isTradingSession;
}
}
function entryPrice() {
if (priceType === 'market') return lastQuotePrice;
return parseFloat(priceInput && priceInput.value) || 0;
@@ -330,7 +342,17 @@
return;
}
var lots = effectiveLots();
var trailingBeEl = document.getElementById('trailing-be');
if (offset === 'open') {
if (!isTradingSession) {
showOrderMsg('不在交易时间段', false);
return;
}
var trailingOn = !!(trailingBeEl && trailingBeEl.checked);
if (trailingOn && !(slInput && slInput.value)) {
showOrderMsg('开启移动保本须填写止损价', false);
return;
}
if (isRiskMode() && lots <= 0) {
showOrderMsg('请填写止损,系统将自动计算手数', false);
return;
@@ -359,7 +381,8 @@
price: price,
order_type: priceType,
stop_loss: slInput && slInput.value ? parseFloat(slInput.value) : null,
take_profit: tpInput && tpInput.value ? parseFloat(tpInput.value) : null
take_profit: tpInput && tpInput.value ? parseFloat(tpInput.value) : null,
trailing_be: !!(trailingBeEl && trailingBeEl.checked)
};
fetch('/api/trade/order', {
method: 'POST',
@@ -379,8 +402,8 @@
showOrderMsg('网络错误,请重试', false);
}).finally(function () {
if (btnOpen) {
btnOpen.disabled = false;
btnOpen.textContent = '开仓';
updateSessionUi();
}
});
}
@@ -471,7 +494,9 @@
'<div class="pos-card-meta">来源 <strong>' + (row.source_label || 'CTP') + '</strong> · 柜台浮盈' +
(slTpBtn ? ' · ' + slTpBtn : '') +
(row.sl_order_active ? ' · <span class="text-profit">止损监控中</span>' : '') +
(row.tp_order_active ? ' · <span class="text-profit">止盈监控中</span>' : '') + '</div>' +
(row.tp_order_active ? ' · <span class="text-profit">止盈监控中</span>' : '') +
(row.trailing_be ? ' · <span class="text-accent">移动保本' +
(row.trailing_r_locked ? '(锁' + row.trailing_r_locked + 'R)' : '') + '</span>' : '') + '</div>' +
'<div class="pos-metrics">' +
'<div class="cell"><label>持仓均价</label><div>' + fmtNum(row.entry_price) + '</div></div>' +
'<div class="cell"><label>当前价格</label><div>' + (row.current_price != null ? fmtNum(row.current_price) : '--') + '</div></div>' +
@@ -646,6 +671,7 @@
return row.stop_loss != null || row.take_profit != null;
});
schedulePositionPoll();
updateSessionUi();
if (!connected) {
if (connecting) {
list.innerHTML = '<div class="empty-hint">CTP 连接中,请稍候…</div>';
@@ -794,6 +820,7 @@
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'visible') pollPositions();
});
updateSessionUi();
scheduleQuote();
});
})();