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:
dekun
2026-06-26 00:35:51 +08:00
parent a23f2c80ca
commit 9f48f22d16
9 changed files with 606 additions and 8 deletions
+62 -5
View File
@@ -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>' +