Gate order cancel to trading hours and sync trade logs from CTP.
Disable cancel UI outside sessions, query exchange fills for records, and label local vs counterparty rows. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -77,6 +77,7 @@
|
||||
.pos-card.is-pending .pos-metrics .cell.pnl-pending label{color:var(--accent)}
|
||||
.pos-close-btn{padding:.4rem .85rem;font-size:.78rem;border-radius:8px;border:1px solid var(--loss);background:var(--loss-bg);color:var(--loss);cursor:pointer;white-space:nowrap;width:auto;flex-shrink:0;min-height:36px}
|
||||
.pos-close-btn:disabled,.pos-close-btn.is-session-off{opacity:.45;cursor:not-allowed;border-color:var(--text-muted);background:var(--card-inner);color:var(--text-muted)}
|
||||
.pos-dismiss-btn:disabled,.pos-dismiss-btn.is-session-off{opacity:.45;cursor:not-allowed;color:var(--text-muted)}
|
||||
.pos-card-meta-line{font-size:.78rem;line-height:1.65;color:var(--text-muted);margin-bottom:.55rem}
|
||||
.pos-card-meta-line strong{color:var(--text)}
|
||||
.pos-card-actions{display:flex;gap:.35rem;flex-shrink:0;align-items:center}
|
||||
|
||||
+62
-5
@@ -204,17 +204,29 @@
|
||||
if (pendingOnly.length) {
|
||||
list.innerHTML = '<div class="empty-hint" style="margin-bottom:.75rem">暂无持仓</div>' +
|
||||
pendingOnly.map(function (p) {
|
||||
var dismissBtn = p.monitor_id ?
|
||||
'<button type="button" class="pos-dismiss-btn" data-monitor-id="' + p.monitor_id + '">取消</button>' : '';
|
||||
var cancelAllowed = p.cancel_allowed !== false && isTradingSession;
|
||||
var actionBtn = '';
|
||||
if (p.monitor_id) {
|
||||
actionBtn = '<button type="button" class="pos-dismiss-btn' +
|
||||
(cancelAllowed ? '' : ' is-session-off') + '"' +
|
||||
(cancelAllowed ? '' : ' disabled title="不在交易时间段"') +
|
||||
' data-monitor-id="' + p.monitor_id + '" data-pending-cancel="1">撤单</button>';
|
||||
} else if (p.order_id && p.source === 'ctp') {
|
||||
actionBtn = '<button type="button" class="pos-dismiss-btn' +
|
||||
(cancelAllowed ? '' : ' is-session-off') + '"' +
|
||||
(cancelAllowed ? '' : ' disabled title="不在交易时间段"') +
|
||||
' data-cancel-order="' + encodeURIComponent(p.order_id) + '">撤单</button>';
|
||||
}
|
||||
return (
|
||||
'<div class="pos-pending-item ' +
|
||||
(p.order_kind === 'stop_loss' ? 'sl' : (p.order_kind === 'take_profit' ? 'tp' : 'ctp')) +
|
||||
'"><span>' + (p.label || '挂单') + ' · ' + (p.symbol || p.symbol_code) + '</span>' +
|
||||
'<span class="pos-pending-right"><strong>' + fmtNum(p.price) + '</strong> · ' +
|
||||
(p.lots || 1) + ' 手' + dismissBtn + '</span></div>'
|
||||
(p.lots || 1) + ' 手' + actionBtn + '</span></div>'
|
||||
);
|
||||
}).join('');
|
||||
bindPendingDismiss(list);
|
||||
bindCancelOrderButtons(list);
|
||||
} else {
|
||||
list.innerHTML = '<div class="empty-hint">暂无持仓。</div>';
|
||||
}
|
||||
@@ -674,6 +686,10 @@
|
||||
opts = opts || {};
|
||||
if (!monitorId) return;
|
||||
var isPending = !!opts.pending;
|
||||
if (isPending && !isTradingSession) {
|
||||
alert('不在交易时间段,无法撤单');
|
||||
return;
|
||||
}
|
||||
var confirmMsg = isPending
|
||||
? '撤销该开仓委托?(将向柜台发送撤单)'
|
||||
: '取消该本地止盈止损监控?(不影响柜台委托)';
|
||||
@@ -706,6 +722,10 @@
|
||||
if (!root) return;
|
||||
root.querySelectorAll('[data-cancel-open]').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
if (!isTradingSession) {
|
||||
alert('不在交易时间段,无法撤单');
|
||||
return;
|
||||
}
|
||||
dismissMonitor(parseInt(btn.getAttribute('data-cancel-open'), 10), btn, { pending: true });
|
||||
});
|
||||
});
|
||||
@@ -715,7 +735,41 @@
|
||||
if (!root) return;
|
||||
root.querySelectorAll('[data-monitor-id]').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
dismissMonitor(parseInt(btn.getAttribute('data-monitor-id'), 10), btn);
|
||||
var isPendingCancel = btn.getAttribute('data-pending-cancel') === '1';
|
||||
dismissMonitor(
|
||||
parseInt(btn.getAttribute('data-monitor-id'), 10),
|
||||
btn,
|
||||
isPendingCancel ? { pending: true } : {}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function bindCancelOrderButtons(root) {
|
||||
if (!root) return;
|
||||
root.querySelectorAll('[data-cancel-order]').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
if (!isTradingSession) {
|
||||
alert('不在交易时间段,无法撤单');
|
||||
return;
|
||||
}
|
||||
var orderId = decodeURIComponent(btn.getAttribute('data-cancel-order') || '');
|
||||
if (!orderId) return;
|
||||
if (!confirm('撤销该柜台委托?')) return;
|
||||
btn.disabled = true;
|
||||
btn.textContent = '撤单中…';
|
||||
fetch('/api/trading/order/cancel', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ order_id: orderId })
|
||||
}).then(function (r) { return r.json(); }).then(function (d) {
|
||||
if (!d.ok) throw new Error(d.error || d.message || '撤单失败');
|
||||
pollPositions();
|
||||
}).catch(function (e) {
|
||||
alert(e.message || '撤单失败');
|
||||
btn.disabled = false;
|
||||
btn.textContent = '撤单';
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -751,8 +805,11 @@
|
||||
var remainMin = row.pending_timeout_min != null
|
||||
? row.pending_timeout_min
|
||||
: (row.auto_cancel_sec != null ? Math.max(1, Math.ceil(row.auto_cancel_sec / 60)) : 5);
|
||||
var cancelAllowed = row.cancel_allowed !== false && isTradingSession;
|
||||
var cancelBtn = row.can_cancel_order ?
|
||||
'<button type="button" class="pos-close-btn" data-cancel-open="' + row.monitor_id + '">撤单</button>' : '';
|
||||
'<button type="button" class="pos-close-btn' + (cancelAllowed ? '' : ' is-session-off') + '"' +
|
||||
(cancelAllowed ? '' : ' disabled title="不在交易时间段"') +
|
||||
' data-cancel-open="' + row.monitor_id + '">撤单</button>' : '';
|
||||
var metaLine =
|
||||
'状态 <strong class="text-accent">挂单中</strong>' +
|
||||
' · 委托价 <strong>' + fmtNum(orderPx) + '</strong>' +
|
||||
|
||||
Reference in New Issue
Block a user